之前遇到一个页面多个状态,绞尽脑汁思考怎么颗粒度最优,现在发现大意了。函数组件更新状态就会重新执行一次,以前是用多个状态管理的组件,现在可以实现一个对象就行了。
安装
npm install immer use-immer
使用
使用方式跟useState
很相似,const [value, setValue] = useImmer(initialState)
。
setValue
接收一个回调函数或者一个值。
当传入回调时,形如:setValue(draft=>{ draft.name=name })
draft 的值可以随意更改。
封装hook
正如上面提到的更新状态的方式: setValue(draft=>{ draft.name=name })
,假如有多个状态分别控制不同的输入/选择组件(受控), 那么也许会在每个 onChange
事件里面写:
const [pay, setPay] = useImmer({
name: '',
country: '',
note: '',
})
<TextField
value={pay.note}
onChange={(value) => setPay(draft=>{draft.note=value})}
/>
重用相似的逻辑,封装成hook
useImmerHandler.ts
import { useCallback } from 'react'
export const useImmerHandler = (setState: React.Dispatch<any>) => {
const handler = useCallback(
(prop: string, value: any) => {
setState((draft: any) => {
draft[prop] = value
})
},
[setState]
)
return handler
}
使用hook
const handlePaypal = useImmerHandler(setPay)
<TextField
value={pay.note}
onChange={(value) => handlePay('note', value)}
/>