问题描述
如何验证结束日期不是过去的日期,也不是距开始日期至少30天的日期?
<TextField
id="startdate"
name="startdate"
label="Start Date"
type="datetime-local"
defaultValue={dateNow}
className={classes.textField}
variant="outlined"
inputRef={register({ required: true })}
InputLabelProps={{
shrink: true,}}
/>
<TextField
id="enddate"
name="enddate"
label="End Date"
type="datetime-local"
defaultValue={dateNext}
className={classes.textField}
variant="outlined"
inputRef={register({ required: true })}
InputLabelProps={{
shrink: true,}}
/>
理想情况下,如果可能,我想进行更改。
日期格式:
enddate: "2020-10-28T13:03"
由于我从未进行过表单验证,因此我不确定尝试从哪里开始。
const validateDate = () => {
if(document.getElementByName("startdate").value < document.getElementByName("enddate").value){
return(error)
}
};
onChange={validateDate()}
解决方法
您的代码与惯用的反应风格相去甚远。因此,首先让我们修复此部分。访问值的反应方式是通过反应内部状态,而不是通过DOM API。
const [startDate,setStartDate] = useState(dateNow)
const [endDate,setEndDate] = useState(dateNext)
// let’s skip this part,it’s a placeholder for now,will come back to it later.
const validate = () => { … }
// for simplicity I omitted other props
<TextField name="startdate" value={startDate} onChange={e => setStartDate(e.target.value)} />
<TextField name="enddate" value={endDate} onChange={e => setEndDate(e.target.value)} />
现在,您可以直接在startDate
函数内部访问endDate
和validate()
。无需致电document.getElementByName
。请记住,这不仅仅是做事的另一种方式。 React更新周期是异步的,值更改不会立即反映到DOM上,使用DOM API会让您很头疼。
返回validate
功能。我首选的调用validate()
的方法不是在onChange
回调内部,而是在useEffect
回调内部。
useEffect(() => {
// do validation here.
},[startDate,endDate])
结尾的[startDate,endDate]
数组称为dep-list。它告诉useEffect
仅在dep-list中任何元素的值更改时才运行回调。有点像onChange
事件,但是只有在提交状态更改后才发出此事件(请记住,状态更改是异步的!)。正是我们想要的。
填写验证码:
useEffect(() => {
// do validation here.
const s = new Date(startDate)
const d = new Date(endDate)
const deltaMs = d.valueOf() - s.valueOf()
const _30_DAYS_IN_MS = 30 * 24 * 60 * 60 * 1000
if (deltaMs < _30_DAYS_IN_MS) {
// notify user of the result:
alert("Invalid Input!")
}
},endDate])
最后将所有内容放在一起,就像:
import React,{ useState,useEffect } from "react"
// …
const [startDate,setEndDate] = useState(dateNext)
useEffect(() => {
// do validation here.
const s = new Date(startDate)
const d = new Date(endDate)
const deltaMs = d.valueOf() - s.valueOf()
const _30_DAYS_IN_MS = 30 * 24 * 60 * 60 * 1000
if (deltaMs < _30_DAYS_IN_MS) {
// notify user of the result:
alert("Invalid Input!")
}
},endDate])
// for simplicity I omitted other props
<TextField name="startdate" value={startDate} onChange={e => setStartDate(e.target.value)} />
<TextField name="enddate" value={endDate} onChange={e => setEndDate(e.target.value)} />
// …
,
对于不受控制的输入,建议使用react refs获取输入,而不是使用文档查询。
- 创建引用并将其附加到每个输入的inputRef道具
- 创建日期时间对象,并获取开始日期和结束日期以及现在的时间戳
- 在
validateEndDate
中进行比较可设置任何错误状态,警报/日志等...您的应用需要做什么
代码
const THIRTY_DAYS = 1000 * 60 * 60 * 24 * 30;
...
const startRef = useRef();
const endRef = useRef();
...
const validateEndDate = () => {
const start = new Date(startRef.current.value).getTime();
const end = new Date(endRef.current.value).getTime();
const now = new Date().getTime();
if (end < now) {
console.error('End date in past!');
}
if (end - start < THIRTY_DAYS) {
console.error('End date not at least 30 days from start date!')
}
}
...
<TextField
inputRef={startRef}
id="startdate"
name="startdate"
label="Start Date"
type="datetime-local"
defaultValue={dateNow}
className={classes.textField}
variant="outlined"
InputLabelProps={{
shrink: true
}}
/>
<TextField
inputRef={endRef}
id="enddate"
name="enddate"
label="End Date"
type="datetime-local"
defaultValue={dateNext}
className={classes.textField}
variant="outlined"
InputLabelProps={{
shrink: true
}}
onChange={validateEndDate}
/>