React Hooks useReducer 使用详解+实现原理+源码分析

简介

useReducer => useState 的高级方案

官网说 useReduceruseState 的替代方案,我觉得说是 useState 的高级方案更合适
因为 useReducer 本质的作用也是更新 state,另外它还支持自定义集成多种更新同一个 state 的规则

使用方法

useReducer定义.png

函数签名如下:

const [state, dispatch] = useReducer(reducer, initialArg, init);

@param 第一个参数为处理 state 改变规则的函数 reducer

reducer 的参数含义:

- @param 第一个参数为要处理的 state  
- @param 第二个参数为 dispatch 绑定的 action(即 dispatch 函数的入参)  
- @return 返回更新 state  

@param 第二个是初始 state

@param 第三个是可选的处理初始 state 的函数 init

@return 返回当前 state

@return 返回 state 对应的 dispatch 方法(触发 state 更新的方法 => 类比 setState

// 处理 初始state
function init(initialCount) {
  return {count: initialCount};
}

// 处理 state 更新规则的函数,并返回新的 state
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>
    </>
  );
}

源码分析👇👇👇

Hook 公共的执行环境判断在useState文章里介绍过点此跳转查看
我们主要来看下 moun 阶段里 mountReducer 的实现 ,和 update 阶段里 updateReducer 的实现。

mount 阶段

mount 阶段 useReducer 调用 mountStateuseReducer 调用 mountReducer
唯一区别就是它们创建的 queuelastRenderedReducer 不一样,useState 默认传入 basicStateReducer => useState 就是有默认 reducer 参数的 useReducer
mountReducer源码.png

update 阶段

updateReducer源码.png

其中循环处理 state 更新队列的原理如下图所示:
场景:现有两次更新 update1、update2,新的更新 update3、update4

循环处理state更新队列的原理流程图.jpg

总结:

其实看到最后啊,我们发现 useStateuseReducer 都只是进行数据更新的处理操作,而把新数据更新渲染到页面上,是 fiber 做的事。

useReducer 里会通过 markWorkInProgressReceivedUpdate 方法标记(也就是通知给 fiber)完成 update 的整合工作,接下来在经过 fiber 的调度,通知浏览器,进而表现在页面上。

这也就导致了函数组件内部获取状态不能实时获取到最新状态的原因,但是 dispatch 提供了函数式入参,这样 react 在执行 queue 的时候,会传递上一步的 state 值到当前函数中。

setCount(prevCount => prevCount + 1)}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值