我已经初始化了一个数组状态,当我更新它时,我的组件不会重新呈现。下面是一个最小的概念证明:

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来开始,并且任何时候它被改变,状态也应该改变。在输入中输入“02”后,App组件不会重新渲染。然而,如果我在onChange函数中添加了一个setTimeout,它在5秒后执行,它显示数字确实已经更新。

对于组件不更新的原因有什么想法吗?

这里是一个概念验证的代码和框。


当前回答

我对此没有任何骄傲,但它确实有效

anotherList = something
setSomething([])
setTimeout(()=>{ setSomething(anotherList)},0)

其他回答

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

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

setNumbers([...old])
  //define state using useState hook
  const [numbers, setNumbers] = React.useState([0, 1, 2, 3]);

  //copy existing numbers in temp
  let tempNumbers = [...numbers];
  // modify/add no
  tempNumbers.push(4);
  tempNumbers[0] = 10;
  // set modified numbers
  setNumbers(tempNumbers);

我正在处理一个数组,其中有对象,我尝试了上面的几个。

我的财产是:

const [options, setOptions] = useState([
{ sno: "1", text: "" },
{ sno: "2", text: "" },
{ sno: "3", text: "" },
{ sno: "4", text: "" },
]);

现在我想在点击按钮时添加更多空白字段的选项,我会使用以下方式来实现我的目的:

<button
    onClick={() => {
      setOptions([...options, { sno: newArray.length + 1, text: "" }]);
    }}
  >

这解决了我的问题,我能够重新渲染组件,并添加一个对象到数组。

useState是一个React钩子,它提供了在函数组件中拥有State的功能。 通常,当useState变量发生变化时,它会通知React重新呈现组件。

{
      let old = numbers;
      old[0] = 1;
      setNumbers(old);
}

在上面的代码中,由于你引用的是同一个变量,它存储的是引用而不是值,因此React不知道最新的变化,因为引用与之前的相同。

为了克服使用下面的hack,它不会复制引用,而是一个深度复制(复制值)

{
      let old = JSON.parse(JSON.stringify(numbers));
      old[0] = 1;
      setNumbers(old);
}

快乐编码:)

Others have already given the technical solution. To anyone confused as to why this happens, is because setSomething() only re renders the component if and only if the previous and current state is different. Since arrays in javascript are reference types, if you edit an item of an array in js, it still doesn't change the reference to the original array. In js's eyes, these two arrays are the same, even though the original content inside those arrays are different. That's why setSomething() fails do detect the changes made to the old array.

注意,如果使用类组件并使用setState()更新状态,那么无论状态是否改变,组件总是会更新。因此,您可以将功能组件更改为类组件作为解决方案。或者按照别人提供的答案去做。