前言
React 的 state 如果存了很多数据,可以使用 setState 去进行合并更新
//...
state={
age: 1,
name: 'qiuqi'
....
}
//...
更新时:
setState({
age: 2
})
由于 hook 本身并没有提供这样可以合并的方法,所以如果声明了很多 State Hook ,就要手动去之前的 state 合并过来,再去写需要更新的数据,例如下面官网上的例子:
function Box() {
const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 });
// ...
}
更新时:
// ...
useEffect(() => {
function handleWindowMouseMove(e) {
// 展开 「...state」 以确保我们没有 「丢失」 width 和 height
setState(state => ({ ...state, left: e.pageX, top: e.pageY }));
}
}, []);
// ...
}
但是可以简单封装下,实现 state 的浅合并,不用每次使用时先展开原来的 state,简化下开发过程,下面是我通过 useState useReducer 来简单地封装了下:
- 使用useState hook
function useSetState<T>(initialState:T) {
const [state, saveState] = useState(initialState);
const setState = useCallback((newState) => {
saveState((prev:T) => ({...prev,...newState}))
}, [])
return [state, setState] as [T, (state:Partial<T>)=> void]
}
- 使用useReducer hook
function useSetState<T>(initialState:T) {
const reducer = (init:T, payload:Partial<T>) => {return {...init,...payload}}
const [state, dispatch] = useReducer(reducer, initialState)
return [state, dispatch] as [T, (state:Partial<T>) => void]
}
最后,使用的时候,很简单,跟 useState 一样的使用方法,两种封装方法都可以这样使用。这适用于简单地数据操作,如果复杂些,还是推荐 hook 本身提供的 useReducer 去控制
const [person, setPerson] = useSetState({
age: 1,
name: 'qiuqi'
})
setPerson({
age: 2
})