如果对象引用未更改,则 useState 正在接受更新 [英] useState is accepting updates if the object reference does not change

查看:54
本文介绍了如果对象引用未更改,则 useState 正在接受更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为 useState 需要有一个新值才能接受更新:

我创建了这个codesandbox来说明我的意思.

我有一个这样的嵌套数据结构

 const state = {姓名:父母",数据: {isExpanded:假,孩子们: [{ name: "one", data: { isExpanded: false } },{ name: "two", data: { isExpanded: false } },{ 名称:三",数据:{ isExpanded:false } }]}};

然后我使用 useState 在状态改变时引起重新渲染:

function App() {const [tree, setTree] = useState(state);const toggleExpanded = 节点 =>{node.data.isExpanded = !node.data.isExpanded;设置树(树);};返回 (<div className="应用程序"><h1>IsExpanded</h1>{tree.data.children.map(child => (<button onClick={() =>切换扩展(子)}>{child.name} - {child.data.isExpanded ?开关"}))}

);}

我每次调用 setTree 时都使用相同的引用并且更新正在发生.

我认为每次发生这种情况都需要一个新的参考?

我可能遗漏了一些东西,但更新不会发生在相同的引用上.

解决方案

这是预期的行为.useState 返回的 setter 在这方面与非钩子 setState 的工作方式相同.它的任何执行都会触发重新渲染,无论它是否是相同的对象引用.

如果你刚刚这样做了:

node.data.isExpanded = !node.data.isExpanded;

如果不调用setTree,则不会发生视觉更新,因为不会触发重新渲染.

通常建议避免通过更改现有状态对象来进行状态更新,因为这会导致某些类型的错误(例如,如果您有任何逻辑将先前状态与新状态进行比较,它们似乎总是如果您通过改变现有对象进行更改,则相同).这可能导致的潜在的、微妙的问题可能会随着未来的 React 并发模式功能而扩展,但 React 不会阻止您这样做.

I thought that useState needed to have a new value for it to accept updates:

I have created thiscodesandbox to illustrate what I mean.

I have a nested data structure like this

   const state = {
      name: "parent",
      data: {
        isExpanded: false,
        children: [
          { name: "one", data: { isExpanded: false } },
          { name: "two", data: { isExpanded: false } },
          { name: "three", data: { isExpanded: false } }
        ]
      }
    };

I then use useState to cause rerenders when the state changes:

function App() {
  const [tree, setTree] = useState(state);

  const toggleExpanded = node => {
    node.data.isExpanded = !node.data.isExpanded;

    setTree(tree);
  };

  return (
    <div className="App">
      <h1>IsExpanded</h1>
      {tree.data.children.map(child => (
        <button onClick={() => toggleExpanded(child)}>
          {child.name} - {child.data.isExpanded ? "on" : "off"}
        </button>
      ))}
    </div>
  );
}

I am using the same reference each time when calling setTree and the updates are happening.

I thought it needed a new reference each time for this to happen?

I might be missing something but is update not happening with the same reference.

解决方案

This is expected behavior. The setter returned by useState works the same in this regard as the non-hook setState. Any execution of it will trigger a re-render and it doesn't matter whether it is the same object reference or not.

If you just did:

node.data.isExpanded = !node.data.isExpanded;

without calling setTree, then no visual update would occur because a re-render would not be triggered.

It is often recommended to avoid doing state updates by changing the existing state object because it can lead to certain types of bugs (e.g. if you have any logic that compares previous state to the new state, they will appear to always be the same if you do changes by mutating the existing objects). And the possible, subtle issues this could lead to would likely expand with future React concurrent mode features, but React does not prevent you from doing it.

这篇关于如果对象引用未更改,则 useState 正在接受更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆