setState 中数组操作的 concat 和 ES6 扩展运算符的区别(React Hooks)
Difference between concat and ES6 spread operator for array manipulation in setState (React Hooks)
我遇到了这个奇怪的错误,我仍然无法理解到底发生了什么。
我正在更新一个状态数组,并希望在保留旧对象的情况下将新对象解析到该数组。
我使用 ES6 的已知方法是使用 spread 运算符作为:
const [stories, setStories] = useState([]);
...
setStories(stories => [...stories, newStories]);
其中 newStories 也是一个对象数组。
但是我得到以下输出:
console.log(stories)
而当我对 concat 做同样的事情时:
setStories(stories => stories.concat(newStories));
它returns符合预期:
console.log(stories)
到目前为止,我认为这两种方法的效果相同。
我也找到了这篇文章,它也证实了我的知识,并且与我得到的上述输出相矛盾。See: Best solution: Spread operator … & a wrapper
以 docs 中的这段代码为例:
let parts = ['shoulders', 'knees'];
let lyrics = ['head', ...parts, 'and', 'toes'];
// ["head", "shoulders", "knees", "and", "toes"]
如您所见,将 parts
数组展开到 lyrics
数组中,它会从数组中提取数据。如果你改为写:
let parts = ['shoulders', 'knees'];
let lyrics = ['head', parts, 'and', 'toes'];
// ["head", ["shoulders", "knees"], "and", "toes"]
你会得到数组。
如果你取一个数组
[{name: 'story1'}, {name: 'story2'}]
并将它放在你的另一个数组中,你会得到:
setStories((stories) => [...stories, newStories]);
[[{name: 'story1'}, {name: 'story2'}]]
如果你再做一次,你会得到:
setStories((stories) => [...stories, newStories]);
[[{name: 'story1'}, {name: 'story2'}],[{name: 'story1'}, {name: 'story2'}]]
因为您只是将数组放入另一个数组。
如果您想从数组中删除对象,您必须spread
将对象放入您的状态。
setStories((prevstate) => [...prevstate, ...newStories]);
然后你得到:
[{},{},{},{}]
因为通过展开,您会将对象从它们当前所在的数组中取出。
作为旁注,我不建议将回调函数的参数命名为与您的状态相同的名称,这会使您对实际引用的内容感到困惑。我见过 prevstate
或者在你的情况下有些人会写 prevStories
等等。只是一个建议。
const a = [{a: 1}, {b: 2}]
const b = [{c: 3}, {d: 4}]
const c = [ ...a, ...b ]
const d = [ a, b ]
const e = [ ...a, b ]
const f = [ a, ...b ]
console.log(c)
console.log(d)
console.log(e)
console.log(f)
您需要将两个数组展开以创建一个新数组
const story1 = [{a: 1}, {b: 2}]
const story2 = [{c: 3}, {d: 4}]
const newStories = [...story1, ...story2];
console.log(newStories);
相反,如果您只将它用于一个数组,它会在 newArray
中创建一个子数组
const story1 = [{a: 1}, {b: 2}]
const story2 = [{c: 3}, {d: 4}]
const newStories = [story1, ...story2];
console.log(newStories);
很简单。 ...
展开运算符将一个数组展开成一个新数组。但是,您的用法不正确:
setStories(stories => [...stories, newStories]); // ❌
setStories(stories => [...stories, ...newStories]); // ✅
第一行不起作用的原因是如果 newStories
是一个数组(它可能是名字),...
是解构和注入所有数组的必要条件项目单独放入新数组。
这更清楚地说明了错误:
const a = [1,2]
const b = [3,4]
const c = [...a, b] // [1,2,[3,4]] ❌
const d = [...a, ...b] // [1,2,3,4] ✅
创建新数组时唯一不使用 ...
展开运算符的情况是添加单个项目时,如下所示:
const a = [1,2]
const b = 5
const c = [...a, ...c] // ❌
const d = [...a, b] // ✅
我遇到了这个奇怪的错误,我仍然无法理解到底发生了什么。
我正在更新一个状态数组,并希望在保留旧对象的情况下将新对象解析到该数组。
我使用 ES6 的已知方法是使用 spread 运算符作为:
const [stories, setStories] = useState([]);
...
setStories(stories => [...stories, newStories]);
其中 newStories 也是一个对象数组。
但是我得到以下输出:
console.log(stories)
而当我对 concat 做同样的事情时:
setStories(stories => stories.concat(newStories));
它returns符合预期:
console.log(stories)
到目前为止,我认为这两种方法的效果相同。
我也找到了这篇文章,它也证实了我的知识,并且与我得到的上述输出相矛盾。See: Best solution: Spread operator … & a wrapper
以 docs 中的这段代码为例:
let parts = ['shoulders', 'knees'];
let lyrics = ['head', ...parts, 'and', 'toes'];
// ["head", "shoulders", "knees", "and", "toes"]
如您所见,将 parts
数组展开到 lyrics
数组中,它会从数组中提取数据。如果你改为写:
let parts = ['shoulders', 'knees'];
let lyrics = ['head', parts, 'and', 'toes'];
// ["head", ["shoulders", "knees"], "and", "toes"]
你会得到数组。
如果你取一个数组
[{name: 'story1'}, {name: 'story2'}]
并将它放在你的另一个数组中,你会得到:
setStories((stories) => [...stories, newStories]);
[[{name: 'story1'}, {name: 'story2'}]]
如果你再做一次,你会得到:
setStories((stories) => [...stories, newStories]);
[[{name: 'story1'}, {name: 'story2'}],[{name: 'story1'}, {name: 'story2'}]]
因为您只是将数组放入另一个数组。
如果您想从数组中删除对象,您必须spread
将对象放入您的状态。
setStories((prevstate) => [...prevstate, ...newStories]);
然后你得到:
[{},{},{},{}]
因为通过展开,您会将对象从它们当前所在的数组中取出。
作为旁注,我不建议将回调函数的参数命名为与您的状态相同的名称,这会使您对实际引用的内容感到困惑。我见过 prevstate
或者在你的情况下有些人会写 prevStories
等等。只是一个建议。
const a = [{a: 1}, {b: 2}]
const b = [{c: 3}, {d: 4}]
const c = [ ...a, ...b ]
const d = [ a, b ]
const e = [ ...a, b ]
const f = [ a, ...b ]
console.log(c)
console.log(d)
console.log(e)
console.log(f)
您需要将两个数组展开以创建一个新数组
const story1 = [{a: 1}, {b: 2}]
const story2 = [{c: 3}, {d: 4}]
const newStories = [...story1, ...story2];
console.log(newStories);
相反,如果您只将它用于一个数组,它会在 newArray
const story1 = [{a: 1}, {b: 2}]
const story2 = [{c: 3}, {d: 4}]
const newStories = [story1, ...story2];
console.log(newStories);
很简单。 ...
展开运算符将一个数组展开成一个新数组。但是,您的用法不正确:
setStories(stories => [...stories, newStories]); // ❌
setStories(stories => [...stories, ...newStories]); // ✅
第一行不起作用的原因是如果 newStories
是一个数组(它可能是名字),...
是解构和注入所有数组的必要条件项目单独放入新数组。
这更清楚地说明了错误:
const a = [1,2]
const b = [3,4]
const c = [...a, b] // [1,2,[3,4]] ❌
const d = [...a, ...b] // [1,2,3,4] ✅
创建新数组时唯一不使用 ...
展开运算符的情况是添加单个项目时,如下所示:
const a = [1,2]
const b = 5
const c = [...a, ...c] // ❌
const d = [...a, b] // ✅