Javascript 反应useState两次更新状态时,第一次更新将被删除
我注意到一个行为,我无法理解如何解决,当我使用this.setState编写基于react类的代码时,我从未遇到过它,但我在使用useState钩子时得到了它 例如:Javascript 反应useState两次更新状态时,第一次更新将被删除,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我注意到一个行为,我无法理解如何解决,当我使用this.setState编写基于react类的代码时,我从未遇到过它,但我在使用useState钩子时得到了它 例如: const Main = () => { const [values, setValues] = useState({val1: '', val2: '', val3: ''}) const func1 = async () => { await setValues({
const Main = () => {
const [values, setValues] = useState({val1: '', val2: '', val3: ''})
const func1 = async () => {
await setValues({
...values,
val1: '111111111'
});
await func2();
}
const func2 = async () => {
result = (fetch some data);
await setValues({
...values,
val2: result
});
}
};
现在,如果运行func1,val1将被更改,但一旦func2完成并设置值,val1将被第二次覆盖,val2将包含值
我做错了什么?我怎样才能解决这个问题
提前谢谢
编辑:
使用钩子时,我看不到在React Chrome Dev工具中输入的值的实际值是多少。
有办法解决这个问题吗?
当我有一个useState包含一个对象时,我可以看到每个对象键的标题。。。现在它隐藏了--在更新相应属性之前,您正在传播状态,请尝试
chunk
您的状态
const Main = () => {
const [value1, setValue1] = useState(null)
const [value2, setValue2] = useState(null)
const func1 = async () => {
setValue1('foo')
await func2();
}
const func2 = async () => {
result = (fetch some data);
await setValue2('foo')
}
};
下面是正在发生的事情
称为更改setValues
(状态尚未更新)val1
再次调用,更改setValues
和val2
其余部分扩展
当
setValues
扩展values
val1
时,它仍然保持初始值,覆盖第一个setValues
调用。请记住,状态的变化是异步反映的我还没有测试过它,但也许它可以作为一种替代方案
有时,当我们需要获取状态中的值时,我们通常在状态中执行spread运算符,但它不能保证值是正确的。对于这些情况,我们最好使用回调调用setState
,该回调从state获取上一个值。因此,您可以使用以下内容:
setValues(prev => ({...prev, val1:'11111'}));
React
useState
还需要一个更新程序来更新组件状态,类似于基于类的组件的setState
的工作方式
注
与类组件中的setState方法不同,useState不会自动合并更新对象。通过将函数更新程序窗体与对象扩展语法相结合,可以复制此行为:
因此,在您的代码中,您可以更新如下:
const Main = () => {
const [values, setValues] = useState({val1: '', val2: '', val3: ''});
const func1 = async () => {
await setValues(prevState => ({
...prevState,
val1: '111111111'
}));
await func2();
}
const func2 = async () => {
result = (fetch some data);
await setValues(prevState => ({
...prevState,
val2: result
}));
}
};
一旦我们注意到func2中的
values
变量在外部作用域中是values
上的clousre,代码的行为就变得清晰了,这实际上是调用useState
时获取的状态的副本
因此,你在func2
中传播的是你所在州的陈旧副本
纠正这种情况的一种方法是使用
这将确保您使用的是状态的更新值。是的,我考虑过这个解决方案。有没有办法在将我的所有数据堆叠到一个对象类型变量中的同时修复它?我想您可以在
func1
中创建中间状态对象,并将其作为参数传递给func2
(而不是func2
直接从状态读取),但Dupocas的答案更好。我正在用另一种方法更新答案。但我肯定会把那些不好的状态分块,我发布了一个简单的通用代码,在实际代码中,func2被func1使用,它也被称为“func3”。将我的所有状态保存在一个对象类型var中更方便:\@Miller我想这就是他所说的无用的意思:)当你把你的应用分成几个小部分时,React钩子工作得非常好,。这是为了避免闭包等复杂问题,您可以使用值来这里。例如,在您的示例中,可能有另一个名为
等的组件。关注点的分离等也会变得更好。此外,GUI更新也更高效,可能会重复
const Main = () => {
const [values, setValues] = useState({val1: '', val2: '', val3: ''});
const func1 = async () => {
await setValues(prevState => ({
...prevState,
val1: '111111111'
}));
await func2();
}
const func2 = async () => {
result = (fetch some data);
await setValues(prevState => ({
...prevState,
val2: result
}));
}
};
setValues((values) => ({...values, val2: result}));