immer是一个第三方模块,可以更加方便的处理不可变状态,其核心实现是利用ES6的proxy。
npm
npm install immer use-immer
yarn
yarn add immer use-immer
produce(currentState, recipe: (draftState) => void | draftState, ?PatchListener): nextState
需求:点击按钮添加一行数据
useState实现
import { useState } from "react"
function App() {
const [list, setList] = useState([
{ id: 1, text: "aaa" },
{ id: 2, text: "bbb" },
{ id: 3, text: "ccc" },
])
const handleClick = () => {
setList([...list,{ id: 4, text: "ddd" }])
}
return (
<div>
<button onClick={handleClick}>点击添加</button>
<ul>
{list.map((item) => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
</div>
)
}
useImmer实现
import { useImmer } from "use-immer"
function App() {
const [list, setList] = useImmer([
{ id: 1, text: "aaa" },
{ id: 2, text: "bbb" },
{ id: 3, text: "ccc" },
])
const handleClick = () => {
setList((draft) => {
draft.push({ id: 4, text: "ddd" })
})
}
return (
<div>
<button onClick={handleClick}>点击添加</button>
<ul>
{list.map((item) => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
</div>
)
}
需求:点击将"小明" 变成 “大明”
useState实现
import { useState } from "react"
import { cloneDeep } from "lodash"
function App() {
const [userInfo, setUserInfo] = useState(
{
name:{
firstname:"小",
lastname:"明"
},
age:23
}
)
const handleClick = () => {
// 方法一:
setUserInfo({
...userInfo,
name:{
...userInfo.name,
firstname:"大"
}
})
// 方法二:也可以使用lodash
const cloneUserInfo = cloneDeep(userInfo)
cloneUserInfo.name.firstname = "大"
setUserInfo(cloneUserInfo)
}
return (
<div>
<button onClick={handleClick}>修改name</button>
<div>{ JSON.stringify(userInfo) }</div>
</div>
)
}
useImmer实现
import { useImmer } from "use-immer"
function App() {
const [userInfo, setUserInfo] = useImmer(
{
name:{
firstname:"小",
lastname:"明"
},
age:23
}
)
const handleClick = () => {
setUserInfo((draft) => {
draft.name.firstname = "大"
})
}
return (
<div>
<button onClick={handleClick}>修改name</button>
<div>{ JSON.stringify(userInfo) }</div>
</div>
)
}