React基础 第十四章(正确更新State中的对象)

在React中,正确地管理和更新state是保持应用性能和可维护性的关键。本文将详细介绍如何在React中更新state中的对象,包括不可变性的概念、如何处理嵌套对象更新,以及使用Immer库简化更新逻辑。

不可变性和state更新

React中的state应该被视为不可变的。这意味着你不应该直接修改state对象,而是应该创建一个新的对象并用它来更新state。

技巧

  • 使用展开运算符...来复制对象并更新state。
  • 对于嵌套对象,从最深的层次开始,为每一层创建新的对象。

示例

jsx 复制代码
const [position, setPosition] = useState({ x: 0, y: 0 });

function handlePointerMove(e) {
  // 创建新的对象来更新state
  setPosition({
    ...position,
    x: e.clientX,
    y: e.clientY
  });
}

注意事项

  • 直接修改state中的对象不会触发组件重新渲染。
  • 使用展开语法时,记住它只能进行浅拷贝。

正确代码

jsx 复制代码
setPosition({
  ...position,
  x: e.clientX
});

错误代码

jsx 复制代码
position.x = e.clientX; // 错误:直接修改了state对象

更新嵌套对象

在React中更新嵌套对象时,你需要为对象的每一层创建一个新的副本。

技巧

  • 使用展开语法为嵌套对象的每一层创建新的副本。
  • 为了避免深层次的展开,可以使用库如Immer来简化过程。

示例

jsx 复制代码
const [person, setPerson] = useState({
  name: 'Niki de Saint Phalle',
  artwork: {
    title: 'Blue Nana',
    city: 'Hamburg',
    image: 'https://i.imgur.com/Sd1AgUOm.jpg'
  }
});

function handleCityChange(e) {
  setPerson({
    ...person,
    artwork: {
      ...person.artwork,
      city: e.target.value
    }
  });
}

注意事项

  • 当更新嵌套对象时,确保你没有遗漏任何层次的复制。
  • 如果对象结构复杂,考虑使用Immer等库来简化更新逻辑。

正确代码

jsx 复制代码
setPerson({
  ...person,
  artwork: {
    ...person.artwork,
    city: 'New Delhi'
  }
});

错误代码

jsx 复制代码
person.artwork.city = 'New Delhi'; // 错误:直接修改了嵌套对象

使用Immer简化状态更新

Immer是一个帮助你以不可变的方式更新复杂state的库。它允许你编写看似直接修改state的代码,但实际上它会为你处理不可变更新。

技巧

  • 使用Immer的produce函数来处理state更新。
  • produce的回调中,你可以直接修改draft对象,而Immer会为你生成新的不可变状态。

示例

jsx 复制代码
import { useImmer } from 'use-immer';

const [person, updatePerson] = useImmer({
  name: 'Niki de Saint Phalle',
  artwork: {
    title: 'Blue Nana',
    city: 'Hamburg',
    image: 'https://i.imgur.com/Sd1AgUOm.jpg'
  }
});

function handleCityChange(e) {
  updatePerson(draft => {
    draft.artwork.city = e.target.value;
  });
}

注意事项

  • Immer使用代理(Proxy)来追踪变化,所以确保你的环境支持Proxy。
  • 使用Immer时,你无需担心深层次的展开和复制。

记住,不可变性是React状态管理的核心原则之一,它能够帮助你避免许多潜在的问题,如性能下降和bug的产生。

相关推荐
奇奇怪怪的33 分钟前
Embedding 模型 10+ 横向评测
前端
陈广亮35 分钟前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端
子兮曰36 分钟前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
敲代码的鱼37 分钟前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
子兮曰44 分钟前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust
Hyyy2 小时前
Function Calling / Tool Use的原理和实现模式
前端·llm·ai编程
爱勇宝2 小时前
从 Ctrl+CV 到 Enter:程序员正在失去什么
前端·后端·程序员
徐小夕2 小时前
我们开源了一款“框架无关”的思维导图编辑器,3分钟集成到任意系统
前端·javascript·github
PBitW2 小时前
GPT训练我的第三天,明白了应该咋说满分回答!😕😕😕
前端·javascript·面试
摸着石头过河的石头3 小时前
前端多仓库管理:从混乱到有序的进化之路
前端