我已经遍历了StackOverflow和Google,但一直无法找到以下解决方案,因此将不胜感激。
假设我在react中使用useState钩子,并因此定义了状态元素:
const [selectedItems, setSelectedItems] = useState([]);
让我们进一步假设我想用对象数组更新这个数组,这样结果数组将是我要放入其中的所有对象的数组。所以,让我们假设我尝试过:
let newItems = [...selectedItems];
newItems.push({a complex object});
setSelectedItems(newItems);
selectedItems将保留[]
。
我已经尝试过六种不同的排列方式来设置此状态,但是都没有成功。我所做的所有事情,selectedItems始终保持[]
。
我既需要将对象推入该数组,又要删除它们……但是我很乐意简单地替换整个数组。问题是,如果我使用功能性React和useState挂钩,则无法找到状态下如何更新此数组。如我所说,如果更新像setSelectedItems([new array of objects])
,那么状态不会改变。
我知道在StackOverflow上已经多次询问类似的问题,但是我找不到与该用例直接可比的任何示例。任何帮助将不胜感激。
答案 0 :(得分:1)
您可以在setter方法中使用旧状态,方法是定义一个匿名函数,例如
const [selectedItems, setSelectedItems] = useState([]);
setSelectedItems((oldItems) => [...oldItems, yourNewItem])
无需通过推销来解构和添加新项目,尤其是如果您想发挥作用的话。
当您正确地迭代视图并使用键告诉React哪些对象时,render方法将更新您的视图。
编辑:为证明这是有效的,这是一个有效的演示。如果这样对您不起作用,则可能是您以某种方式使用了数组,而react无法分辨出数组之间的差异,因此不会显示任何重新渲染。
const Demo = () => {
const [selectedItems, setSelectedItems] = React.useState(["a", "b", "c"]);
const removeItem = (item) => {
setSelectedItems((oldItems) => [
...oldItems.filter(i => i !== item),
`Removed item ${item}`
])
}
return (<div>
{selectedItems.map(item => <button key={"item-"+item}
onClick={() => removeItem(item)}>Remove Item {item}</button>)}
</div>);
}
ReactDOM.render(<Demo />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="app"></div>
答案 1 :(得分:0)
重新发布答案,因为先前答案中的链接不起作用
您可以尝试这样的事情
const [items, setItems] = useState([])
let updatedList = [...items, ...moreItems]
setItems(updatedList)
“ moreItems”还是对象数组。如果要添加单个对象,可以尝试
let updatedList = [...items, {key : 'value'}]
setItems(updatedList)
检查此链接