immer介绍

半兽人 发表于: 2025-08-05   最后更新时间: 2025-08-05 09:18:42  
{{totalSubscript}} 订阅, 110 游览

immer 是一个 JavaScript 的不可变数据(immutable data)管理库,主要用于简化对状态(state)的不可变更新操作,常见于 React、Redux 等状态管理场景。

1. 背景问题

在 React 或 Redux 中,我们通常需要保证状态 不可变(immutable),因为:

  1. 不可变性可以触发组件重渲染(通过浅比较 === 快速判断状态是否变化)。
  2. 数据修改更安全,避免意外修改共享引用,产生难以排查的 bug。

但是手动维护不可变对象很繁琐,例如:

const state = {
  user: { name: "Tom", age: 20 },
  hobbies: ["coding", "gaming"]
}

// 改名字时必须拷贝一层层对象
const newState = {
  ...state,
  user: {
    ...state.user,
    name: "Jerry"
  }
}

写起来很麻烦。

2. immer 的作用

immer 通过 Proxy 代理,允许你像修改可变对象一样写代码,但最终自动生成一个不可变的新对象。

安装:

npm install immer

使用:

import { produce } from "immer"

const state = {
  user: { name: "Tom", age: 20 },
  hobbies: ["coding", "gaming"]
}

// 用 immer 更新状态
const newState = produce(state, (draft) => {
  draft.user.name = "Jerry"     // 像修改普通对象一样
  draft.hobbies.push("music")   // 直接改数组
})

console.log(newState)
// {
//   user: { name: "Jerry", age: 20 },
//   hobbies: ["coding", "gaming", "music"]
// }

特点:

  1. state 保持原样(不可变)。
  2. newState 是新对象,只有被修改的部分是新的引用。

3. 核心 API

  1. produce(baseState, recipe)

    • baseState:原始状态
    • recipe(draft):对 draft 进行修改即可
    • 返回新的不可变对象
  2. current(draft)

    • 可以查看 draft 的当前快照(调试用)
  3. original(draft)

    • 获取 draft 对应的原始对象

4. 在 React 中的使用

在 React 的 useState 或 Redux Toolkit 中,immer 很常用:

import { useState } from "react"
import { produce } from "immer"

function App() {
  const [user, setUser] = useState({ name: "Tom", age: 20 })

  const changeName = () => {
    setUser(
      produce(user, (draft) => {
        draft.name = "Jerry"
      })
    )
  }

  return (
    <div>
      <p>{user.name}</p>
      <button onClick={changeName}>改名</button>
    </div>
  )
}

Redux Toolkit 内部也是用 immer 来处理 createSlice 的状态更新。

5. 总结

  • immer 的本质:通过 Proxy 实现 可变写法 → 不可变数据 的自动转换。
  • 优势:写法简洁、减少对象深拷贝、避免手动维护不可变性。
  • 应用场景:React、Redux、状态管理、复杂数据结构更新。
更新于 2025-08-05

查看React更多相关的文章或提一个关于React的问题,也可以与我们一起分享文章