如何使用useState在功能性React中正确更新数组

时间:2020-08-31 20:16:48

标签: arrays reactjs use-state

我已经遍历了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上已经多次询问类似的问题,但是我找不到与该用例直接可比的任何示例。任何帮助将不胜感激。

2 个答案:

答案 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)

使用有效的示例https://stackblitz.com/edit/react-6enrwj

检查此链接