如何使用 useState 在函数式 React 中正确更新数组

How to properly update an array in functional React with useState

我遍历了 Whosebug 和 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]) 这样更新,那么状态不会改变。

我知道类似的问题已在 Whosebug 上被问过多次,但我找不到任何与此用例直接比较的示例。任何帮助将不胜感激。

您可以通过定义匿名函数在 setter 方法中使用旧状态,例如

const [selectedItems, setSelectedItems] = useState([]);

setSelectedItems((oldItems) => [...oldItems, yourNewItem])

无需通过推送解构和添加新项目,特别是如果你想发挥作用的话。

渲染方法将更新您的视图,当您正确地迭代它并使用键告诉 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>

重新发布答案,因为之前答案中的 link 无效

你可以试试这样的

const [items, setItems] = useState([])

let updatedList = [...items, ...moreItems]
setItems(updatedList)

其中“moreItems”又是一个对象数组。如果你想添加单个对象,你可以试试这个

let updatedList = [...items, {key : 'value'}]
setItems(updatedList)

检查这个 link 用一个工作示例 https://stackblitz.com/edit/react-6enrwj