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

相关推荐
卸任4 小时前
Vibe coding工具使用心得
前端·ai编程
brien95 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance5 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M5 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写5 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李5 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易5 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马5 小时前
前沿视界
前端
kyriewen5 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易6 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员