表单中的 React Hooks 自定义验证无法更新多个状态
React Hooks custom validation in form cannot update multiple states
如果在 handleValidate()
触发期间所有字段都留空,则只有 error
中的 confirmPasswordIsError
和 confirmPassword
的状态会被更新,其他的会被更新。我不知道哪里出了问题?
function Register() {
const classes = useStyles();
const { handleRegister } = useContext(AuthenticationContext);
const [form, setForm] = useState({
username: '',
password: '',
confirmPassword: ''
})
const [error, setError] = useState({
usernameIsError: false,
usernameError: '',
passwordIsError: false,
passwordError: '',
confirmPasswordIsError: false,
confirmPasswordError: ''
});
const handleValidate = () => {
if (!form.username) {
setError({
...error,
usernameIsError: true,
usernameError: '用戶名稱不能留空'
})
}
if (!form.password) {
setError({
...error,
passwordIsError: true,
passwordError: '密碼不能留空'
})
}
if (!form.confirmPassword) {
setError({
...error,
confirmPasswordIsError: true,
confirmPasswordError: '確認密碼不能留空'
})
return false;
}
// if (form.confirmPassword !== form.password) {
// setError({
// ...error,
// confirmPasswordIsError: true,
// confirmPasswordError: '確認密碼與密碼不相同'
// })
// return false;
// }
return true;
}
const handleChange = (e) => {
const { name, value } = e.target
setForm({
...form,
[name]: value
})
}
const handleSubmit = (e) => {
e.preventDefault();
const isFormValid = handleValidate();
console.log(isFormValid)
if (isFormValid) {
handleRegister(form.username, form.password)
}
}
return (
<Container>
<Grid
container
justify="center"
>
<Grid item>
<Paper className={classes.paper} elevation={3} >
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<TextField
error={error.usernameIsError}
helperText={error.usernameError}
className={classes.input}
fullWidth
required
name="username"
size="small"
label="帳號"
variant="outlined"
value={form.username}
onChange={handleChange}
/>
<TextField
error={error.passwordIsError}
helperText={error.passwordError}
className={classes.input}
fullWidth
required
name="password"
size="small"
label="密碼"
type="password"
variant="outlined"
value={form.password}
onChange={handleChange}
/>
<TextField
error={error.confirmPasswordIsError}
helperText={error.confirmPasswordError}
className={classes.input}
fullWidth
required
name="confirmPassword"
size="small"
label="確認密碼"
type="password"
variant="outlined"
value={form.confirmPassword}
onChange={handleChange}
/>
<Button className={classes.button} fullWidth variant="contained" color="primary" type="submit">註冊</Button>
</form>
</Paper>
</Grid>
</Grid>
</Container>
)
}
如果在渲染周期内对多个更新进行排队,则使用功能状态更新,以便后续更新不会覆盖先前排队的更新。
当您使用正常更新时,您将处于 error
状态,在当前渲染周期的回调范围内关闭,因此每次更新都会消除之前的更新。功能状态更新允许您从以前的状态更新。
const handleValidate = () => {
if (!form.username) {
setError(error => ({
...error,
usernameIsError: true,
usernameError: '用戶名稱不能留空'
}))
}
if (!form.password) {
setError(error => ({
...error,
passwordIsError: true,
passwordError: '密碼不能留空'
}))
}
if (!form.confirmPassword) {
setError(error => ({
...error,
confirmPasswordIsError: true,
confirmPasswordError: '確認密碼不能留空'
}))
return false;
}
if (form.confirmPassword !== form.password) {
setError(error => ({
...error,
confirmPasswordIsError: true,
confirmPasswordError: '確認密碼與密碼不相同'
}))
return false;
}
return true;
}
如果在 handleValidate()
触发期间所有字段都留空,则只有 error
中的 confirmPasswordIsError
和 confirmPassword
的状态会被更新,其他的会被更新。我不知道哪里出了问题?
function Register() {
const classes = useStyles();
const { handleRegister } = useContext(AuthenticationContext);
const [form, setForm] = useState({
username: '',
password: '',
confirmPassword: ''
})
const [error, setError] = useState({
usernameIsError: false,
usernameError: '',
passwordIsError: false,
passwordError: '',
confirmPasswordIsError: false,
confirmPasswordError: ''
});
const handleValidate = () => {
if (!form.username) {
setError({
...error,
usernameIsError: true,
usernameError: '用戶名稱不能留空'
})
}
if (!form.password) {
setError({
...error,
passwordIsError: true,
passwordError: '密碼不能留空'
})
}
if (!form.confirmPassword) {
setError({
...error,
confirmPasswordIsError: true,
confirmPasswordError: '確認密碼不能留空'
})
return false;
}
// if (form.confirmPassword !== form.password) {
// setError({
// ...error,
// confirmPasswordIsError: true,
// confirmPasswordError: '確認密碼與密碼不相同'
// })
// return false;
// }
return true;
}
const handleChange = (e) => {
const { name, value } = e.target
setForm({
...form,
[name]: value
})
}
const handleSubmit = (e) => {
e.preventDefault();
const isFormValid = handleValidate();
console.log(isFormValid)
if (isFormValid) {
handleRegister(form.username, form.password)
}
}
return (
<Container>
<Grid
container
justify="center"
>
<Grid item>
<Paper className={classes.paper} elevation={3} >
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<TextField
error={error.usernameIsError}
helperText={error.usernameError}
className={classes.input}
fullWidth
required
name="username"
size="small"
label="帳號"
variant="outlined"
value={form.username}
onChange={handleChange}
/>
<TextField
error={error.passwordIsError}
helperText={error.passwordError}
className={classes.input}
fullWidth
required
name="password"
size="small"
label="密碼"
type="password"
variant="outlined"
value={form.password}
onChange={handleChange}
/>
<TextField
error={error.confirmPasswordIsError}
helperText={error.confirmPasswordError}
className={classes.input}
fullWidth
required
name="confirmPassword"
size="small"
label="確認密碼"
type="password"
variant="outlined"
value={form.confirmPassword}
onChange={handleChange}
/>
<Button className={classes.button} fullWidth variant="contained" color="primary" type="submit">註冊</Button>
</form>
</Paper>
</Grid>
</Grid>
</Container>
)
}
如果在渲染周期内对多个更新进行排队,则使用功能状态更新,以便后续更新不会覆盖先前排队的更新。
当您使用正常更新时,您将处于 error
状态,在当前渲染周期的回调范围内关闭,因此每次更新都会消除之前的更新。功能状态更新允许您从以前的状态更新。
const handleValidate = () => {
if (!form.username) {
setError(error => ({
...error,
usernameIsError: true,
usernameError: '用戶名稱不能留空'
}))
}
if (!form.password) {
setError(error => ({
...error,
passwordIsError: true,
passwordError: '密碼不能留空'
}))
}
if (!form.confirmPassword) {
setError(error => ({
...error,
confirmPasswordIsError: true,
confirmPasswordError: '確認密碼不能留空'
}))
return false;
}
if (form.confirmPassword !== form.password) {
setError(error => ({
...error,
confirmPasswordIsError: true,
confirmPasswordError: '確認密碼與密碼不相同'
}))
return false;
}
return true;
}