【问题标题】:Is using the destructured state to calculate new state with react hooks safe?使用解构状态来计算带有反应挂钩的新状态是否安全?
【发布时间】:2019-10-20 09:42:44
【问题描述】:

使用解构状态计算新状态安全吗?

例如:

const [clickCount, setClickCount] = useState(0);
//then later
setClickCount(clickCount + 1)

我知道使用 this.state + 1 的类是不行的,最好使用 setState 的重载来提供先前的状态。鉴于文档使用了类似于我上面的示例并且没有提及这一点,我认为它是安全的。直到我发现 setState 动作签名是:

type SetStateAction<S> = S | ((prevState: S) => S);

如果它是安全的,我现在很好奇为什么这可以选择性地为函数提供先前的状态。否则,当您解构了应该同步的当前状态时,您什么时候需要这个?

编辑:

作为参考,这是文档中关于 setState with this.state 的说明:

setState() 不会立即改变 this.state 而是创建一个 等待状态转换。调用 this 后访问 this.state 方法可能会返回现有值。

不保证 setState 调用的同步操作 并且调用可能会被批处理以提高性能。

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    类似于类组件中的setState API 如何接受一个函数作为参数,钩子也接受同样的。

    来自official docs:您始终可以传递一个函数,以防您想使用先前重载的新状态。

    这是否意味着也像 this.state 一样,不能保证突变已经发生在使用钩子的解构状态?

    尽管在类和钩子中获取状态的方式不同,setState API 本身在两者中都有相似的实现。它仍然是异步的。因此,无论您如何访问状态(类中的this.state 或钩子中的state),都可能根据您的代码使用过时的状态。 示例:

    function Counter({initialCount}) {
      const [count, setCount] = useState(initialCount);
      return (
        <>
          Count: {count}
          <button onClick={() => setCount(count + 1)}>Reset</button>
          <button onClick={() => setCount(count + 2)}>+</button>
        </>
      );
    }
    
    
    class Counter extends React.Component {
      constructor() {
        super();
        this.state = initialCount;
      }
    
      render() {
        <>
          Count: {count}
          <button onClick={() => this.setState(count + 1)}>Reset</button>
          <button onClick={() => this.setState(count + 2)}>+</button>
        </>
      }
    }
    

    以两种方式实现了相同的组件。但是它们都不能保证之前的状态值会在后续的setState 语句中使用。因此,在这些情况下,最好同时在钩子和类中传递函数。

    【讨论】:

    • 感谢您的回答,尽管给出了这个选项的具体问题,但这是否意味着也像这样。state 不能保证使用钩子的解构状态发生了突变?
    • 是的。钩子状态也可能不会发生突变。在上面的示例中,在第一个 setCount 之后,count 的值不会在第二个 setCount 之前发生突变。这是由于 React 批处理状态更新。它与类完全相同。只是他们已经转移到不同的 API。实现仍然相同,因此这里也存在常见的陷阱。
    猜你喜欢
    • 2021-10-23
    • 1970-01-01
    • 2022-11-01
    • 2021-02-11
    • 1970-01-01
    • 2020-10-28
    • 2021-10-02
    • 2021-07-19
    • 2021-05-19
    相关资源
    最近更新 更多