在下面的代码中,除非我将先前的状态传递给状态设置调用(“ setForm”),否则表单无法正确更新。
要查看其运行效果,请按原样运行代码,控制台将显示“ true”,表明它可以正常工作。那是使用'validate1'函数。如果将其替换为“ validate2”(不使用以前的状态),它将无法打印“ true”。
似乎在validate2中,由于这些调用的异步特性,第二个setForm调用将覆盖第一个setForm调用的form.long状态。但是validate1为什么起作用?为什么使用以前的状态会导致它起作用?任何有关此行为的文档都将非常有帮助。
(我可以通过使用一个设置两个字段的setForm来使validate2起作用,但是下面的代码旨在显示在调用setForm的两种方式中(带有或不带有先前状态)有所不同。)
const {useState, useEffect} = React;
function LoginForm() {
const [form, setForm] = useState({
username: "",
password: "",
long: null
});
useEffect(() => {
console.log(form.long);
}, [form.long]);
const validate1 = (e) => {
e.preventDefault();
setForm((prevState) => ({
...prevState,
long: form.password.length >=3 ? true : false
}));
setForm((prevState) => ({
...prevState,
username: "*****"
}));
};
const validate2 = (e) => {
e.preventDefault();
setForm({
...form,
long: form.password.length >=3 ? true : false
});
setForm({
...form,
username: "*****"
});
};
const updateField = (e) => {
setForm({
...form,
[e.target.name]: e.target.value
});
};
return (
<form onSubmit={validate1}>
<label>
Username:
<input value={form.username} name="username" onChange={updateField} />
</label>
<br />
<label>
Password:
<input
value={form.password}
name="password"
type="password"
onChange={updateField}
/>
</label>
<br />
<button>Submit</button>
</form>
);
}
// Render it
ReactDOM.render(
<LoginForm/>,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
答案 0 :(得分:0)
为什么validate1可以工作?为什么使用以前的状态会导致它起作用?
setForm({
...form,
long: form.password.length >=3 ? true : false
});
setForm({
...form,
username: "*****"
});
第二个form
中setForm
的值仍然是旧值,直到下一次重新渲染为止。它不反映从先前的form
起更新的setForm
。
反应setState
和useState
不会直接对状态对象进行更改。
setState
和useState
为React核心创建队列以更新React组件的状态对象。
因此出于性能原因,更新React状态的过程是异步的。这就是为什么更改不会立即生效的原因。
https://linguinecode.com/post/why-react-setstate-usestate-does-not-update-immediately
答案 1 :(得分:0)
在React documentation中,他们提到以下内容,
如果下一个状态取决于当前状态,我们建议使用 更新器函数形式,而不是:
this.setState((state) => {
return {quantity: state.quantity + 1};
});
这是validate1起作用的原因,因为对setForm的第二次调用取决于先前的setForm调用状态,并且如果使用了updater函数形式,则该状态将是最新的。