返回首页

{...}展开运算符和react

布莱克2025-12-27 13:27已编辑
Tip:文章封面与内容无关,作者旅游时拍摄,因为没什么值得把四季都错过!

React持续学习中

关于react的状态更新,如果逻辑如下:

modules = modules.map((module) => {
  // module为{}对象
  if (module.name === "info") {
    // ❌ 错误:直接修改原对象
    module.isShow = type !== "test";
    return module; // 返回的是同一个引用
  }
  return module;
});

上述写法会有问题,正确的写法应该是什么呢?

modules = modules.map((module) => {
  if (module.name === "info") {
    // ✅ 正确:创建新对象
    return { ...module, isShow: type !== "test" };
  }
  return module;
});

关于React 的重新渲染机制

  • React 通过 浅比较(shallow comparison) 来判断组件是否需要重新渲染
  • 对于对象和数组,React 比较的是 引用(reference),而不是内容
  • 如果引用相同,React 会认为数据没有变化,不会触发重新渲染

📊 两种写法的对比

写法返回结果React 是否检测到变化
{ ...module, isShow: newValue }新对象,新引用✅ 是,会重新渲染
module.isShow = newValue; return module;原对象,相同引用❌ 否,不会重新渲染

React 的渲染优化机制(特别是浅比较)选择为什么比较引用而非内容❓❓

1.比较引用是 O(1) 时间复杂度的操作,而深度比较内容可能是 O(n) 甚至更复杂

2. React 遵循 "引用不可变性" 模式,这源于函数式编程思想:

  • 状态应该是不可变的
  • 更新时创建新对象,而不是修改原对象
  • 这使得变化检测变得简单且高效

(第一反应是更新时创建新对象,不会造成内存泄漏吗❓)

在使用不可变更新时,我们的操作是用新引用替换旧引用。一旦旧引用被替换,并且没有其他地方持有它,旧的不可变对象就变成了“不可达”的数据,最终会被垃圾回收器安全清理

// 示例:安全的不可变更新
const [state, setState] = useState({ items: [] });

const addItem = (newItem) => {
  // 创建全新的对象,赋予新引用
  const newState = { items: [...state.items, newItem] };
  setState(newState); // 新引用替换旧引用

  // 此时,旧的 `state` 对象如果没有其他变量引用它,将在下次GC时被回收
  // 旧的 `state.items` 数组同理
};

🎯 {...}在react中的应用场景

1.状态管理

// 更新对象状态
const [user, setUser] = useState({ name: 'John', age: 25 });
setUser({ ...user, age: 26 });  // ✅ 只更新age,保留其他属性

// 更新数组中的对象
const [todos, setTodos] = useState([{ id: 1, text: 'Learn React', done: false }]);
setTodos(todos.map(todo => 
  todo.id === 1 ? { ...todo, done: true } : todo
));

2.

assistant