两次更新状态时反应useState,第一次更新被删除

时间:2019-10-02 13:14:00

标签: javascript reactjs react-hooks

我注意到一种行为,我无法理解该如何解决,在我使用this.setState编写基于React的类时,我从未遇到过这种行为,但是在使用useState挂钩时却发现了。

例如:

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完成并且我们setValues,第二次val1将被覆盖,而val2将包含值。

我在做什么错了,我该如何解决?

预先感谢!

编辑:

enter image description here

使用钩子时,我看不到在React Chrome Dev工具中输入的值的正确含义。 有没有办法来解决这个问题 ? 当我有一个包含对象的useState时,我可以看到每个对象键的标题...现在隐藏了-_-

4 个答案:

答案 0 :(得分:2)

您正在传播状态,然后再更新相应的属性,请尝试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,更改其余部分val2spreading

setValues传播values val1时,它仍保持其初始值,覆盖了第一个setValues调用。记住,状态变化是异步反映的

答案 1 :(得分:1)

反应useState还需要一个functional更新程序来更新组件状态,类似于基于类的组件setState的工作方式。

  

注意

     

与在类组件中找到的setState方法不同,useState不会自动合并更新对象。您可以通过将函数更新程序形式与对象传播语法结合在一起来复制此行为:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

因此,您可以在代码中进行如下更新:

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
    }));
  }
};

答案 2 :(得分:0)

我尚未对其进行测试,但是也许它可以替代。

有时,当我们需要获取状态值时,通常会在状态内执行散布运算符,但不能保证该值是正确的值。在这种情况下,我们最好通过回调从状态中获取先前的值来调用setState。因此,您可以使用以下内容:

setValues(prev => ({...prev, val1:'11111'}));

答案 3 :(得分:0)

一旦我们注意到func2中的values变量在外部范围的values上是clousre,这实际上就是状态{被叫。

因此,您在useState中的传播是您状态的陈旧副本。

一种纠正此问题的方法是使用functional update

func2

这将确保您使用的是状态的更新值。