设置数组等于另一个数组或使用三个点之间的区别
Difference between setting array equal to another one, or using three dots
在 React 中使用钩子并使用数组作为状态时,我发现使用 setter 函数仅更新该状态数组的一个元素不会重新渲染组件。我是这样做的:
const [listCollapsed, setListCollapse] = useState(Array(props.list.length).fill(false));
const expandCollapse = (ind) => {
let newListCollapsed = listCollapsed;
newListCollapsed[ind] = !listCollapsed[ind];
setListCollapse(newListCollapsed);
}
其中 expandCollapse 是在按下列表元素时调用的函数。我发现将函数的第一行更改为:
let newListCollapsed = [...listCollapsed];
成功了。我想知道对此的解释是什么。
您的第一个版本通过直接 修改 状态打破了 React 的主要规则之一(更多关于 in this part of the docs)。行
let newListCollapsed = listCollapsed;
只是使 newListCollapsed
和 listCollapsed
都引用同一个数组(用作状态的数组),不会 复制数组.当你这样做时,你会得到这样的结果:
state:Ref5461−−−−−−−−−−−−−−−−+
\ +−−−−−−−−−−−+
listCollapsed:Ref5461−−−−−−−−−−+−−−−>| (array) |
/ +−−−−−−−−−−−+
newListCollapsed:Ref5461−−−−−+ | 0: false |
| 1: false |
| ... |
+−−−−−−−−−−−+
所以
setListCollapse(newListCollapsed);
不执行任何操作,因为它设置的是状态已包含的相同数组。 React 没有看到任何变化。
但是这一行:
let newListCollapsed = [...listCollapsed];
将数组复制 到一个新数组中(使用扩展符号将其条目扩展到由 []
文字创建的新数组中),所以你有:
state:Ref5461−−−−−−−−−−−−−−−−+
\ +−−−−−−−−−−−+
listCollapsed:Ref5461−−−−−−−−−−+−−−−>| (array) |
+−−−−−−−−−−−+
| 0: false |
| 1: false |
| ... |
+−−−−−−−−−−−+
+−−−−−−−−−−−+
newListCollapsed:Ref8465−−−−−−−−−−−−>| (array) |
+−−−−−−−−−−−+
| 0: false |
| 1: false |
| ... |
+−−−−−−−−−−−+
所以当你调用 setListCollapse(newListCollapsed);
时,它不是一回事,并且发生了变化。这是正确的做法。
(这些图中的 Ref####
值是概念性的。它们是两个数组的对象引用。对象引用告诉 JavaScript 引擎对象在哪里在内存中。您永远不会在代码中看到对象引用的实际值。)
在 React 中使用钩子并使用数组作为状态时,我发现使用 setter 函数仅更新该状态数组的一个元素不会重新渲染组件。我是这样做的:
const [listCollapsed, setListCollapse] = useState(Array(props.list.length).fill(false));
const expandCollapse = (ind) => {
let newListCollapsed = listCollapsed;
newListCollapsed[ind] = !listCollapsed[ind];
setListCollapse(newListCollapsed);
}
其中 expandCollapse 是在按下列表元素时调用的函数。我发现将函数的第一行更改为:
let newListCollapsed = [...listCollapsed];
成功了。我想知道对此的解释是什么。
您的第一个版本通过直接 修改 状态打破了 React 的主要规则之一(更多关于 in this part of the docs)。行
let newListCollapsed = listCollapsed;
只是使 newListCollapsed
和 listCollapsed
都引用同一个数组(用作状态的数组),不会 复制数组.当你这样做时,你会得到这样的结果:
state:Ref5461−−−−−−−−−−−−−−−−+ \ +−−−−−−−−−−−+ listCollapsed:Ref5461−−−−−−−−−−+−−−−>| (array) | / +−−−−−−−−−−−+ newListCollapsed:Ref5461−−−−−+ | 0: false | | 1: false | | ... | +−−−−−−−−−−−+
所以
setListCollapse(newListCollapsed);
不执行任何操作,因为它设置的是状态已包含的相同数组。 React 没有看到任何变化。
但是这一行:
let newListCollapsed = [...listCollapsed];
将数组复制 到一个新数组中(使用扩展符号将其条目扩展到由 []
文字创建的新数组中),所以你有:
state:Ref5461−−−−−−−−−−−−−−−−+ \ +−−−−−−−−−−−+ listCollapsed:Ref5461−−−−−−−−−−+−−−−>| (array) | +−−−−−−−−−−−+ | 0: false | | 1: false | | ... | +−−−−−−−−−−−+ +−−−−−−−−−−−+ newListCollapsed:Ref8465−−−−−−−−−−−−>| (array) | +−−−−−−−−−−−+ | 0: false | | 1: false | | ... | +−−−−−−−−−−−+
所以当你调用 setListCollapse(newListCollapsed);
时,它不是一回事,并且发生了变化。这是正确的做法。
(这些图中的 Ref####
值是概念性的。它们是两个数组的对象引用。对象引用告诉 JavaScript 引擎对象在哪里在内存中。您永远不会在代码中看到对象引用的实际值。)