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

函数签名如下:
const [state, dispatch] = useReducer(reducer, initialArg, init);
state 改变规则的函数 reducerreducer 的参数含义:
- @param 第一个参数为要处理的 state
- @param 第二个参数为 dispatch 绑定的 action(即 dispatch 函数的入参)
- @return 返回更新 state
statestate 的函数 initstatestate 对应的 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 阶段 useReducer 调用 mountState,useReducer 调用 mountReducer
唯一区别就是它们创建的 queue 中 lastRenderedReducer 不一样,useState 默认传入 basicStateReducer => useState 就是有默认 reducer 参数的 useReducer


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

其实看到最后啊,我们发现 useState 和 useReducer 都只是进行数据更新的处理操作,而把新数据更新渲染到页面上,是 fiber 做的事。
在 useReducer 里会通过 markWorkInProgressReceivedUpdate 方法标记(也就是通知给 fiber)完成 update 的整合工作,接下来在经过 fiber 的调度,通知浏览器,进而表现在页面上。
这也就导致了函数组件内部获取状态不能实时获取到最新状态的原因,但是 dispatch 提供了函数式入参,这样 react 在执行 queue 的时候,会传递上一步的 state 值到当前函数中。
setCount(prevCount => prevCount + 1)}