为什么 useState 不触发重新渲染?

新手上路,请多包涵

我已经初始化了一个数组状态,当我更新它时,我的组件不会重新渲染。这是一个最小的概念验证:

 function App() {
  const [numbers, setNumbers] = React.useState([0, 1, 2, 3]);
  console.log("rendering...");
  return (
    <div className="App">
      {numbers.map(number => (
        <p>{number}</p>
      ))}
      <input
        type="text"
        value={numbers[0].toString()}
        onChange={newText => {
          let old = numbers;
          old[0] = 1;
          setNumbers(old);
        }}
      />
    </div>
  );
}

根据这段代码,似乎输入应该包含数字 0 开始,并且任何时候改变,状态也应该改变。在input中输入“02”后,App组件并没有重新渲染。但是,如果我在 5 秒后执行的 onChange 函数中添加一个 setTimeout,则表明数字确实已更新。

关于为什么组件不更新的任何想法?

这是一个带有概念证明的 CodeSandbox

原文由 Ryan Z 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 867
2 个回答

您正在调用 setNumbers 并将其传递给它已有的数组。你已经改变了它的一个值,但它仍然是同一个数组,我怀疑 React 没有看到任何重新渲染的理由,因为状态没有改变;新数组是旧数组。

避免这种情况的一种简单方法是将数组扩展到一个新数组中:

 setNumbers([...old])

原文由 ray 发布,翻译遵循 CC BY-SA 4.0 许可协议

你需要复制 numbers 像这样 let old = [...numbers];

useState 仅当它发生变化时才更新值,所以如果它是 44 并且它变成了 7 它将更新。但是它怎么知道数组或对象是否发生了变化。它是引用,所以当你做 let old = numbers 你只是传递一个引用而不是创建一个新的

原文由 evgeni fotia 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题