当前位置: 首页 > 知识库问答 >
问题:

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

邴俊民
2023-03-14

我已经初始化了一个数组状态,当我更新它时,我的组件不会重新渲染。以下是一个最低限度的概念证明:

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”后,应用程序组件不会重新渲染。但是,如果我在5秒后执行的onChange函数中添加setTimeout,则表明数字确实已更新。

对为什么组件不更新有什么想法吗?

这是一个带有概念证明的代码沙盒。

共有3个答案

呼延曜灿
2023-03-14

其他人已经给出了技术解决方案。对于任何对为什么会发生这种情况感到困惑的人来说,这是因为set某物()只有当且仅当前一个状态和当前状态不同时才会重新呈现组件。由于javascript中的数组是引用类型,如果您在js中编辑数组的项,它仍然不会更改对原始数组的引用。在js看来,这两个数组是相同的,尽管这些数组中的原始内容是不同的。这就是set某物()失败检测对旧数组所做的更改的原因。

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

陆俊捷
2023-03-14

你需要复制数字这样let old=[...数字];

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

越俊艾
2023-03-14

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

避免这种情况的一种简单方法是将阵列分散到新阵列中:

setNumbers([...old])
 类似资料:
  • 尽管试图避免所有记录在案的陷阱,阻止React在状态更改后重新渲染,但我仍然无法解决我的问题: } 从每个长方体组件调用update函数,并触发长方体网格上新颜色的指定。 试图避免常见的错误: 颜色数组只有在通过扩展运算符从状态复制后才被修改 通过setState()传递新数组 此外,我还处理了两个组件中函数的实例绑定 但是,尽管onClick成功触发了状态更改,但不会进行重新渲染。我在这里缺少的

  • 也许你们中的一些人可以帮我睁开眼睛。 我不明白为什么在这段代码中:https://codesandbox.io/s/use-state-renders-twice-6r1xl组件应用程序在安装并单击按钮时呈现两次(console.log被调用两次) 代码: 结果: 它只是一个功能组件挂钩!

  • 问题内容: 我正在尝试设计一个通知组件,在某些情况下通知会出现(例如连接问题,成功的修改等)。 我需要几秒钟后通知才能消失,因此我正在触发状态更改,以从通知内部的Redux状态删除通知。 我可以看到状态确实发生了变化,但是React-Redux并没有重新渲染父组件,因此通知仍然出现在DOM上。 这是我的Redux减速器: 和我的React组件(和): 问题答案: 您已经正确连接了所有内容,但是缺少

  • 问题内容: 我的代码中有一个。我已添加。但是它还是没有被触发。我已经尝试了很多时间,但是没有找到解决方案。 但是控制台中没有任何内容。请建议我我在做什么错。 问题答案: FocusListener不是JComboBox的适当监听器,另外一个监听器可以创建无限循环(尤其是可编辑的JComboBox), 的FocusListener是异步的,有时是太难捕捉事件是正确的订单特别是在案件JComponen

  • 问题内容: Parent(在我的示例中)组件通过Child()组件呈现一个数组。父级决定更改数组中的属性,React触发子级重新渲染的方式是什么? 调整数据后,我想出的只是在Parent中。这是触发更新的hack还是React方法? JS小提琴:https: //jsfiddle.net/69z2wepo/7601/ 问题答案: 这里的问题是您要在中存储状态,而不是。由于此组件是mutating