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的产生。

相关推荐
竹林8187 小时前
wagmi v2 监听合约事件踩坑记:从 `useContractEvent` 到 `watchContractEvent`,我重构了三版才搞定实时数据流
前端·javascript
天若有情6737 小时前
纯HTML+Tailwind单页作品集网站——零框架静态前端完整源码
前端·html
WebGirl7 小时前
H5唤起app前端实现方案
前端
heimeiyingwang7 小时前
【架构实战】SQL注入与XSS防御:常见Web漏洞的系统性修复
前端·sql·架构
Larcher8 小时前
从零实现一个可运行的 RAG - LangChain、内存向量库与检索增强生成
前端·javascript
饼饼饼8 小时前
React 组件间传参好痛苦?试试这一套"优雅组合拳":Context 与 Refs 实战
前端
qq_419854059 小时前
空间网格管理器
前端·javascript·html
qingmiaozhuan9 小时前
电脑录屏没有声音还能补救吗?音频采集链路详解及4种技术方案
前端·电脑·音视频·开发工具·电脑录屏·电脑录屏软件
天若有情6739 小时前
Dev_Portfolio 个人主页html网页源码分享!!!
前端·html·源码·个人主页