学习React 的第十二天 React与immerjs

231 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情

1. 简介

Immer是mobx的作者写的一个immutable库,核心实现是利用ES6的proxy,以最小的成本解决了JS的不可变数据结构。

React的范式就是数据不可变,如果根据这个范式去操作修改数据的话比较繁琐,我们更习惯使用可变数据,因此Immer就是解决这个问题 ,并且不需要学习心得API

2. 代码处理

1. 安装库

pnpm i immer

2. 简单使用

1.不使用immer

  1. 我们有一组数据,我们需要更新其中一个,并再添加一个。但是,我们不想改变原始的baseState
    const baseState = [
        {
            title: "Learn TypeScript",
            done: true
        },
        {
            title: "Try Immer",
            done: false
        }
    ]
  1. 常规操作,使用深浅拷贝,再进行修改
const nextState = baseState.slice()
nextState[1] = {
    ...nextState[1],
    done: true
}
nextState.push({title: "添加第三个", done: false})
  1. 再次遍历新的数组nextState就能显示出数据了
  2. 这样的做法过于麻烦,数据过多不便于维护

2.使用immer

使用 Immer,会将所有更改应用到临时 draft,它是 baseState 的代理。一旦你完成了所有的修改与添加,Immer 将根据对 draft state 的改变而生成新的nextState。这意味着可以通过简单地修改数据来与数据交互,同时保留不可变数据的所有好处。

const nextState = produce(baseState, draft => {
    draft[1].done = true
    draft.push({title: "第三组数据", done: false})
})

3. 与React 结合使用

  1. 需要使用一个新的附加库 use-immer
  2. 使用 use-immer的hook useImmer 代替React的useState
import React from 'react';
import {useImmer} from "use-immer";


function App() {
    const [baseState, setBaseState] = useImmer([
        {
            title: "Learn TypeScript",
            done: true
        },
        {
            title: "Try Immer",
            done: false
        }
    ])

    function changeData() {
        setBaseState(draft => {
            draft[1].done = true
            draft.push({title: "第三组数据", done: true})
        })
    }

    return (
        <div>
            <div>{baseState.map(item => <p>title: {item.title}: done: {String(item.done)}</p>)}</div>
            <hr/>
            <button onClick={changeData}>数据修改</button>
        </div>
    );
}

export default App
  1. 通过上面使用方法,我们直接可以超简单的就像Vue中操作数据一样了,又有了写Vue的感觉。

4. 还可以在Redux状态管理库中使用

  1. 使用produce包装 reducer 函数
import produce from "immer"

const todosReducer = produce((draft, action) => {
    switch (action.type) {
        case "setDone":
            draft[0].done = action.payload
            break
        default:
            break
    }
})
  1. 其他操作不变

3. 总结

  1. 学习了immerjs 让我们对数据修改的操作更加简单放心
  2. 使用写原生JS的方式操作React的不可变数据