问题描述
由于缺乏知识和经验,我偶然发现了一种奇怪的行为。 我有一个在另一个内部调用的组件,如下所示:
<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);
};
有人可以解释为什么会发生这种情况吗?
解决方法
发生这种情况是因为 const updatedRoles=roles
在内存中为完全相同的对象创建了另一个名称,因此您对 updatedRoles
所做的一切都反映在 roles
中,换句话说,您改变了状态。 roles.slice()
另一方面创建一个新的独立对象。当您将这个新对象传递给 setState
时,React 可以看到差异并触发重新渲染,但是当您将它传递给另一个名称 roles
时,React 认为不需要做任何事情,因为 { {1}} 和 updatedRoles
是一回事。
在您的第一个示例中,您使用相同的数组实例来更新状态。
React 只检查浅等式。它不是迭代项目。
.slice()
创建一个新数组。
如果您的状态是数组,请始终创建一个新数组。
Slice 创建原始数组的浅拷贝,这意味着它返回的对象与 roles
本身不同,即使其内容可能相同。
当你执行 setRoles(roles)
时,你实际上是在内存中发送完全相同的对象,当 React 在决定是否重新渲染之前比较 props 时,它没有检测到任何差异。然而,当你执行 setRoles(roles.slice())
时,你在内存中传递了一个不同的变量,所以 React 认为 props 和重新渲染发生了变化。