React Hooks系列之useReducer

useReducer介绍

useState 的替代方案,它更适合一些逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等的特定场景
类似 Redux 中的功能 reducer。
它接收一个形如 (state, action) => newState 的reducer,并返回当前的 state 以及与其配套的 dispatch 方法。

const [state, dispatch] = useReducer(reducer, initState, initAction)

参数介绍

  • reducer 是一个函数,就是一个函数类似 (state, action) => newState 的函数,传入 上一个 state 和 本次的 action, 根据 action 状态处理并更新 state
  • initState 是初始化的 state,也就是默认值
  • initAction 是useReducer 初次执行时被处理的 action,其实惰性初始化,这么做可以将用于计算 state 的逻辑提取到 reducer 外部,这也为将来对重置 state 的action 做处理提供了便利

返回值state,dispatch介绍

  • state 状态值
  • dispatch 是更新 state 的方法,他接受 action 作为参数。useReducer 只需要调用dispatch(action) 方法传入 action 即可更新 state

useContext 可以解决组件间的数据共享问题,而useReducer 可以解决复杂状态管理的问题,如果把他们结合起来使用,就可以实现 redux 的功能了

useRuducer使用

基本使用

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, {
    count: 0
  });
  return (
    <>
      点击次数: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}

惰性初始化

你可以选择惰性地创建初始 state。为此,需要将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被 设置为 init(initialArg)。

这么做可以将用于计算 state 的逻辑提取到 reducer 外部,这也为将来对重置 state 的 action 做处理提供了便利:

function init(initialCount) {
  return {count: initialCount};
}

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    case 'reset':
      return init(action.payload);
    default:
      throw new Error();
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);
  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>
        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

注意: React 会确保 dispatch 函数的标识是稳定的,并且不会在组件重新渲染时改变,这就是为什么可以安全地从 useRffect 或 useCallback 的依赖列表中省略 dispatch

posted @ 2022-04-19 09:39  Tommy_marc  阅读(155)  评论(0编辑  收藏  举报