教程 immer tutorial

数组方法

Immer 支持所有标准的数组方法,并且可以像操作普通数组一样操作 draft 数组。下面是一些常见的数组操作示例:

添加元素

javascript
import produce from "immer"

const todos = [
  { id: 1, text: "学习 Immer", done: false },
  { id: 2, text: "构建应用", done: false }
]

const newTodos = produce(todos, draft => {
  // 添加到数组末尾
  draft.push({ id: 3, text: "编写文档", done: false })
  
  // 添加到数组开头
  draft.unshift({ id: 0, text: "初始化项目", done: true })
  
  // 在指定位置插入
  draft.splice(2, 0, { id: 1.5, text: "深入学习", done: false })
})

删除元素

javascript
const todos = [
  { id: 1, text: "学习 Immer", done: false },
  { id: 2, text: "构建应用", done: false },
  { id: 3, text: "编写文档", done: false }
]

const newTodos = produce(todos, draft => {
  // 删除最后一个元素
  draft.pop()
  
  // 删除第一个元素
  draft.shift()
  
  // 删除指定位置的元素
  draft.splice(0, 1)
  
  // 根据条件删除元素
  const index = draft.findIndex(todo => todo.id === 2)
  if (index !== -1) {
    draft.splice(index, 1)
  }
})

修改元素

javascript
const todos = [
  { id: 1, text: "学习 Immer", done: false },
  { id: 2, text: "构建应用", done: false }
]

const newTodos = produce(todos, draft => {
  // 修改指定索引的元素
  draft[0].done = true
  
  // 根据条件修改元素
  const todo = draft.find(todo => todo.id === 2)
  if (todo) {
    todo.text = "构建更好的应用"
  }
  
  // 修改所有元素
  draft.forEach(todo => {
    todo.updatedAt = new Date().toISOString()
  })
})

排序和反转

javascript
const todos = [
  { id: 3, text: "编写文档", done: false },
  { id: 1, text: "学习 Immer", done: true },
  { id: 2, text: "构建应用", done: false }
]

const newTodos = produce(todos, draft => {
  // 排序
  draft.sort((a, b) => a.id - b.id)
  
  // 反转
  draft.reverse()
})

注意事项

  • 使用 map、filter、reduce 等方法时,它们会返回新的数组,而不是修改原数组。你需要将结果赋值回 draft:
javascript
const todos = [
  { id: 1, text: "学习 Immer", done: false },
  { id: 2, text: "构建应用", done: false },
  { id: 3, text: "编写文档", done: false }
]

const newTodos = produce(todos, draft => {
  // 使用 filter 过滤元素
  draft.splice(0, draft.length, ...draft.filter(todo => !todo.done))
  
  // 使用 map 转换元素
  draft.splice(0, draft.length, ...draft.map(todo => ({
    ...todo,
    done: false
  })))
})
  • 只有数值属性和 length 属性会被保留在数组上,自定义属性不会被保留。