You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何编辑对象数组?edit1与edit2方案孰优?

React状态更新方案对比:edit1 vs edit2

我有一个React状态变量,是包含user对象的数组,user对象有id和name字段。现在需要修改列表中用户的name属性,写了两种实现方式:

const App = () => {
  
  const [users, setUsers] = useState([]);
  
  useEffect(async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    const users = await response.json();
    setUsers(users);
  }, [])
  
  const edit1 = (id) => {
    const newUsers = users.map(user => {
      if(user.id === id) {
        user.name = 'John Doe';
      } 
      return user;
    });    
    setUsers(newUsers);
  }
  
  const edit2 = (id) => {
    const newUsers = users.map(user => ({
      ...user,
      name: user.id === id ? 'Jane Doe' : user.name
    }));
    setUsers(newUsers);
  }
  
  return(
    <div>
      <button onClick={() => edit1(2)}>Edit-1</button>
      <button onClick={() => edit2(5)}>Edit-2</button>
      <ul>
        {users.map((user) => (<li key={user.key}>{user.name}</li>))}
      </ul>
    </div>
  );
}

两种方法都能完成需求,但edit1是直接修改原user对象,仅生成新数组;edit2则创建新对象和新数组。想知道哪种方案更优,还有没有其他实现方式?


方案优劣分析

edit2是更优的方案,原因如下:

  • React状态更新遵循不可变原则:edit1中直接修改原user对象的name属性,会污染原始状态。虽然这次通过新数组的引用变化触发了重渲染,但如果后续有组件使用React.memo、useMemo或useCallback依赖该user对象的引用,会因为原对象被修改导致无法正确触发更新,或引发不必要的重渲染。
  • edit2通过扩展运算符...user创建新的user对象,保留原对象其他属性的同时仅修改name字段,完全符合不可变更新规则,状态变化可预测,也能配合React的性能优化API正常工作。

其他实现方式

  1. 函数式状态更新:当更新依赖前一个状态时,使用setUsers的函数形式,避免因状态异步更新导致的错误:
const edit3 = (id) => {
  setUsers(prevUsers => prevUsers.map(user => ({
    ...user,
    name: user.id === id ? 'New Name' : user.name
  })));
}
  1. 用immer简化不可变更新:immer允许以"可变"的写法编写代码,内部自动转换为不可变更新,代码更简洁:
import { produce } from 'immer';

const edit4 = (id) => {
  setUsers(produce(prevUsers => {
    const targetUser = prevUsers.find(user => user.id === id);
    if (targetUser) {
      targetUser.name = 'Immer Updated Name';
    }
  }));
}

内容的提问来源于stack exchange,提问作者Parvez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:05:34