React Hook简单封装实现state的浅合并,更好的操作state

2,503 阅读1分钟

前言

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 来简单地封装了下:
  1. 使用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]
}
  1. 使用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
})