ReactJS useState 钩子:我可以使用状态变量本身更新对象数组吗?

ReactJS useState hook: Can I update array of objects using the state variable itself?

我有:


const [list, setList] = useState([]);

在组件的某处,我想做:

list[index][someKey] = some_updated_value;

setList(list);

这有效吗?

或者,更好的做法是:

const newList = list;

newList[index][someKey] = some_updated_value;

setList(newList);

如果这样更好,为什么?

我可能是错的,但我认为任何一种方式都是直接改变状态。我认为这样做会更好:

setList(list.map((item,i)=>{
  if(index === i){
    return {...item, [someKey]: some_update_value};
  }
  return item;
}))

这两种实现都将被视为状态突变,应该避免,因为这在 React 中是 anti-pattern。 React 使用浅引用相等性检查作为其 Reconciliation 过程的一部分,即如果状态块是与前一个渲染周期相同的对象引用,则假定值相同并跳过重新渲染。

  • 版本 1

    这只是直接改变状态对象。

      list[index][someKey] = some_updated_value; // <-- mutation!
      setList(list);
    
  • 版本 2

    这也直接改变了状态对象,因为 newList 是对 list 的引用。

      const newList = list; // <-- newList reference to state
      newList[index][someKey] = some_updated_value; // <-- mutation!
      setList(newList);
    

React 状态更新的想法是应用不可变更新模式。这是您创建任何状态和正在更新的嵌套状态的浅表副本的地方。这通常也与功能状态更新相结合,您将回调函数传递给更新程序函数,该函数传递了先前的状态以进行更新。这有助于避免陈旧的状态封闭。

示例:

setList(list => list.map((item, i) => // Array.protptype.map creates new array
  i === index
    ? {                               // new object reference for updated item
      ...item,                        // shallow copy previous item state
      [someKey]: newValue             // overwrite property being updated
    }
    : item
));

好的文档: