如果您将状态值分配给另一个变量然后更改状态,React 不会触发重新渲染

Posted

技术标签:

【中文标题】如果您将状态值分配给另一个变量然后更改状态,React 不会触发重新渲染【英文标题】:React does not trigger rerender if you assign state value to another variable and then change the state 【发布时间】:2021-05-27 18:12:38 【问题描述】:

由于缺乏知识和经验,我偶然发现了一种奇怪的行为。 我在另一个内部调用了一个组件,如下所示:

            <CustomSelectionButtons
              values=roleTypes
              label="Roles:"
              onSelect=setUserRoles
              selected=roles
            />

roles 是一个状态变量,通过 onSelect 方法 (setUserRoles) 设置。 这里是:

  const setUserRoles = (button: AccountsAndRolesUnion) => 
   const updatedRoles: AccountsAndRolesUnion[] = roles; //this is the state variable.

   /* doing something with the local **updatedRoles** array */

   setRoles(updatedRoles);
  ;

如果我使用这样的代码,组件不会在 setRoles 钩子调用后重新渲染。 但是,如果我用 roles.slice() 分配局部变量,一切都会按预期工作,组件会重新呈现。 所以,这行得通:

const setUserRoles = (button: AccountsAndRolesUnion) => 
  const updatedRoles: AccountsAndRolesUnion[] = roles.slice(); //slicing the state variable.

  /* doing something with the local **updatedRoles** array */

  setRoles(updatedRoles);
;

谁能解释为什么会这样?

【问题讨论】:

【参考方案1】:

Slice 创建原始数组的浅表副本,这意味着它返回的对象与roles 本身不同,即使其内容可能相同。

当你做setRoles(roles) 时,你实际上是在内存中发送完全相同的对象,当 React 在决定是否重新渲染之前比较 props 时,它没有检测到任何差异。但是,当您执行 setRoles(roles.slice()) 时,您在内存中传递了一个不同的变量,因此 React 认为 props 和重新渲染发生了变化。

【讨论】:

【参考方案2】:

在您的第一个示例中,您使用相同的数组实例来更新状态。 React 只检查浅层相等。它不是迭代项目。 .slice() 创建一个新数组。 如果您的状态是数组,请始终创建一个新数组。

【讨论】:

【参考方案3】:

发生这种情况是因为const updatedRoles=roles 为内存中完全相同的对象创建了另一个名称,因此您对updatedRoles 所做的一切都会反映在roles 中,换句话说,您会改变状态。另一方面,roles.slice() 创建一个新的独立对象。当你将这个新对象传递给 setState 时,React 可以看到差异并触发重新渲染,但是当你只是将它传递给 roles 时,React 不需要做任何事情,因为 updatedRoles 和 @ 987654328@是同一个东西。

【讨论】:

以上是关于如果您将状态值分配给另一个变量然后更改状态,React 不会触发重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

React 状态在其分配的变量更改时更改

是否可以将一个功能“分配”给另一个功能?

为什么将一个对象的值分配给另一个对象的值,然后重新分配原始对象会更改两个对象?

Python:通过将对象分配给另一个对象来修改它

SwiftUI 如何将@Published 分配给另一个@Published

XCode 中的 Git 状态永远不会从“A”更改