react.js typescript spread(...) 仅添加最后一个元素
react.js typescript spread(...) adding only the last element
我正在尝试在 react.js
中的数组中添加一个元素
this.state.chat_list.map(elem => {
if (
elem.name
.toLowerCase()
.indexOf(this.props.searching_username.toLowerCase()) !== -1
) {
this.setState(
{ searched_chat_list: [...this.state.searched_chat_list, elem.name] },
() => {
console.log(this.state.searched_chat_list);
}
);
}
});
这是代码。
问题是它只添加结果中的最后一个元素
假设我有 a,ab,c,d,aad
,如果我用 a
搜索,它只会 return aad
而不是 a,ab,aad
。
我该如何解决?
你肯定想要这样的东西:
this.setState(prev => ({
searched_chat_list: [
...prev.searched_chat_list,
prev.chat_list.filter(el =>
el.name
.toLowerCase()
.includes(this.props.searching_username.toLowerCase())
),
],
}))
我更正了几处:
如果你在过滤,你应该使用 filter
而不是 map
(如果你想做一个 for-each,那么使用 forEach
不是 map
。map
用于将一个数组映射到另一个数组,这不是你在这里做的。
我将一个函数传递给 setState
,这样我就不会使用陈旧的状态值。您的 setState
仅设置最后一个值的原因是因为您在循环的每次迭代中都不断覆盖先前的值。
例如,假设您做了这样的事情:
// State
const state = {
myArray: [1, 2]
}
// Let's add this array to the one in state
[3, 4, 5, 6].forEach(num => {
setState({
// state.myArray is always [1, 2]
myArray: [...state.myArray, num]
})
})
你认为这里的结果会是什么?你期望 [1, 2, 3, 4, 5, 6]
,但结果实际上是 [1, 2, 6]
.
状态仅在重新渲染时更新,因此 state.myArray
的值始终为 [1, 2]
,即使在循环的最后一次迭代中也是如此 - 因为组件尚未重新渲染, 所以状态还没有更新。
基本上你是这样做的:
setState({myArray: [1, 2, 3]})
setState({myArray: [1, 2, 4]})
setState({myArray: [1, 2, 5]})
setState({myArray: [1, 2, 6]})
现在你明白为什么只将最后一项添加到数组了吗?
如果您的新状态值取决于之前的状态值,您应该始终将函数传递给 setState:
// Let's pass a function to setState this time
[3, 4, 5, 6].forEach(num => {
setState(prev => ({
// prev is always the most up-to-date state value
myArray: [...prev.myArray, num]
}))
})
prev
值始终是最新的状态值,因此这里的结果将是 [1, 2, 3, 4, 5, 6]
,这是我们想要的,尽管在您的情况下,您没有无论如何都不需要迭代数组。
简化它,首先过滤而不是添加:
const newList = this.state.chat_list.filter(
elem =>
elem.name
.toLowerCase()
.indexOf(this.props.searching_username.toLowerCase()) !== -1
);
this.setState(
{
searched_chat_list: [...this.state.searched_chat_list, ...newList]
},
() => console.log(this.state.searched_chat_list)
);
我正在尝试在 react.js
中的数组中添加一个元素this.state.chat_list.map(elem => {
if (
elem.name
.toLowerCase()
.indexOf(this.props.searching_username.toLowerCase()) !== -1
) {
this.setState(
{ searched_chat_list: [...this.state.searched_chat_list, elem.name] },
() => {
console.log(this.state.searched_chat_list);
}
);
}
});
这是代码。
问题是它只添加结果中的最后一个元素
假设我有 a,ab,c,d,aad
,如果我用 a
搜索,它只会 return aad
而不是 a,ab,aad
。
我该如何解决?
你肯定想要这样的东西:
this.setState(prev => ({
searched_chat_list: [
...prev.searched_chat_list,
prev.chat_list.filter(el =>
el.name
.toLowerCase()
.includes(this.props.searching_username.toLowerCase())
),
],
}))
我更正了几处:
如果你在过滤,你应该使用
filter
而不是map
(如果你想做一个 for-each,那么使用forEach
不是map
。map
用于将一个数组映射到另一个数组,这不是你在这里做的。我将一个函数传递给
setState
,这样我就不会使用陈旧的状态值。您的setState
仅设置最后一个值的原因是因为您在循环的每次迭代中都不断覆盖先前的值。
例如,假设您做了这样的事情:
// State
const state = {
myArray: [1, 2]
}
// Let's add this array to the one in state
[3, 4, 5, 6].forEach(num => {
setState({
// state.myArray is always [1, 2]
myArray: [...state.myArray, num]
})
})
你认为这里的结果会是什么?你期望 [1, 2, 3, 4, 5, 6]
,但结果实际上是 [1, 2, 6]
.
状态仅在重新渲染时更新,因此 state.myArray
的值始终为 [1, 2]
,即使在循环的最后一次迭代中也是如此 - 因为组件尚未重新渲染, 所以状态还没有更新。
基本上你是这样做的:
setState({myArray: [1, 2, 3]})
setState({myArray: [1, 2, 4]})
setState({myArray: [1, 2, 5]})
setState({myArray: [1, 2, 6]})
现在你明白为什么只将最后一项添加到数组了吗?
如果您的新状态值取决于之前的状态值,您应该始终将函数传递给 setState:
// Let's pass a function to setState this time
[3, 4, 5, 6].forEach(num => {
setState(prev => ({
// prev is always the most up-to-date state value
myArray: [...prev.myArray, num]
}))
})
prev
值始终是最新的状态值,因此这里的结果将是 [1, 2, 3, 4, 5, 6]
,这是我们想要的,尽管在您的情况下,您没有无论如何都不需要迭代数组。
简化它,首先过滤而不是添加:
const newList = this.state.chat_list.filter(
elem =>
elem.name
.toLowerCase()
.indexOf(this.props.searching_username.toLowerCase()) !== -1
);
this.setState(
{
searched_chat_list: [...this.state.searched_chat_list, ...newList]
},
() => console.log(this.state.searched_chat_list)
);