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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56266575/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:36:18  来源:igfitidea点击:

Why is useState not triggering re-render?

javascriptreactjsreact-hooks

提问by Ryan Z

I've initialized a state that is an array, and when I update it my component does not re-render. Here is a minimal proof-of-concept:

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

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

Based on this code, it seems that the input should contain the number 0 to start, and any time it is changed, the state should change too. After entering "02" in the input, the App component does not re-render. However, if I add a setTimeout in the onChange function which executes after 5 seconds, it shows that numbers has indeed been updated.

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

Any thoughts on why the component doesn't update?

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

Here is a CodeSandboxwith the proof of concept.

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

回答by ray hatfield

You're calling setNumbersand passing it the array it already has. You've changed one of its values but it's still the same array, and I suspect React doesn't see any reason to re-render because state hasn't changed; the new array is the old array.

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

One easy way to avoid this is by spreading the array into a new array:

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

setNumbers([...old])

回答by evgeni fotia

You need to copy numberslike so let old = [...numbers];

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

useStatedoesn't update the value only if it has changed so if it was 44and it became 7it will update. but how can it know if an array or object have changed. it's by reference so when you do let old = numbersyou are just passing a reference and not creating a new one

useState仅当值已更改时才更新该值,因此如果它已更改44并变为7它,它将更新。但是它如何知道数组或对象是否已更改。它是通过引用,所以当你这样做时,let old = numbers你只是传递一个引用而不是创建一个新的