如果你将状态值赋给另一个变量,然后改变状态,React不会触发渲染



由于缺乏知识和经验,我偶然发现了一种奇怪的行为。我有一个在另一个内部调用的组件,看起来像这样:

<CustomSelectionButtons
values={roleTypes}
label="Roles:"
onSelect={setUserRoles}
selected={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);
};

谁能解释一下为什么会这样?

Slice创建了原始数组的浅拷贝,这意味着它返回的对象与roles本身不同,尽管其内容可能相同。

当你做setRoles(roles)时,你实际上是在内存中发送完全相同的对象,当React在决定是否重新渲染之前比较道具时,它不会检测到任何差异。然而,当你做setRoles(roles.slice())时,你在内存中传递了一个不同的变量,所以React认为在道具和重新渲染中有一个变化。

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

在第一个示例中,您使用相同的数组实例来更新状态。React只检查浅层的相等。它不是遍历这些项。.slice()创建一个新数组。如果你的状态是一个数组,总是创建一个新的数组。

最新更新