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

相关推荐
大波V59 分钟前
用 nvm 彻底重装 Node 12.22.12(确保干净)
前端
和和和24 分钟前
React Scheduler为何采用MessageChannel调度?
前端·javascript
Ric97024 分钟前
Mac上Git不识别文件名大小写修改?一招搞定!
前端
和和和29 分钟前
前端应该知道的浏览器知识
前端·javascript
狗哥哥31 分钟前
前端基础数据中心:从混乱到统一的架构演进
前端·vue.js·架构
树深遇鹿35 分钟前
数据字典技术方案实战
前端·javascript·架构
大布布将军1 小时前
一种名为“Webpack 配置工程师”的已故职业—— Vite 与“零配置”的快乐
前端·javascript·学习·程序人生·webpack·前端框架·学习方法
JosieBook1 小时前
【Vue】02 Vue技术——搭建 Vue 开发框架:在VS Code中创建一个Vue项目
前端·javascript·vue.js
科普瑞传感仪器1 小时前
航空航天制造升级:机器人高精度力控打磨如何赋能复合材料加工?
java·前端·人工智能·机器人·无人机·制造
前端开发呀1 小时前
成为开源项目的Contributor:从给uView-pro 贡献一次PR开始
前端·微信小程序