“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情”
1. 简介
Immer是mobx的作者写的一个immutable库,核心实现是利用ES6的proxy,以最小的成本解决了JS的不可变数据结构。
React的范式就是数据不可变,如果根据这个范式去操作修改数据的话比较繁琐,我们更习惯使用可变数据,因此Immer就是解决这个问题 ,并且不需要学习心得API
2. 代码处理
1. 安装库
pnpm i immer
2. 简单使用
1.不使用immer
- 我们有一组数据,我们需要更新其中一个,并再添加一个。但是,我们不想改变原始的baseState
const baseState = [
{
title: "Learn TypeScript",
done: true
},
{
title: "Try Immer",
done: false
}
]
- 常规操作,使用深浅拷贝,再进行修改
const nextState = baseState.slice()
nextState[1] = {
...nextState[1],
done: true
}
nextState.push({title: "添加第三个", done: false})
- 再次遍历新的数组nextState就能显示出数据了
- 这样的做法过于麻烦,数据过多不便于维护
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 结合使用
- 需要使用一个新的附加库 use-immer
- 使用 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
- 通过上面使用方法,我们直接可以超简单的就像Vue中操作数据一样了,又有了写Vue的感觉。
4. 还可以在Redux状态管理库中使用
- 使用produce包装 reducer 函数
import produce from "immer"
const todosReducer = produce((draft, action) => {
switch (action.type) {
case "setDone":
draft[0].done = action.payload
break
default:
break
}
})
- 其他操作不变
3. 总结
- 学习了immerjs 让我们对数据修改的操作更加简单放心
- 使用写原生JS的方式操作React的不可变数据