首先可以参考官方对useReducer的解释:https://react.docschina.org/docs/hooks-reference.html#usereducer
其实官网已经很详细了,下边就我的经验总结一下;
useReducer是什么
此hook是useState
的替代方案。与其说是替代,我更愿意用优化来形容,熟悉 Redux 的话,就已经知道它如何工作了。它接收一个形如 (state, action) => newState
的 reducer,并返回当前的 state 以及与其配套的 dispatch
方法,通过变更state的值来触发页面数据更新,下边看下简单的定义方法:
const initialState = {count: 0}; 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 Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'decrement'})}>-</button> <button onClick={() => dispatch({type: 'increment'})}>+</button> </> ); }
此定义为基本方法,可以看出,useReducer实际可以定义多个state,然后通过一个方法统一管理当前页面的state。
为什么使用useReducer
这个和什么时候使用可以放到一起来说,现在假如有个页面,有列表分页参数,有数十个搜索调价参数,有是个父页面传过来的联动参数,此时我们不仅需要维护分页参数,维护页面本身的搜索参数,还要维护父页面带过来的参数,更有甚者,需要变更父页面带过来的参数,通知父页面进行响应的操作。
在新的react版本中,已经对state进行优化,通个方法内如果有多个setState的操作,会统一变更后再更新页面数据,这比之前每次执行setState都要变更页面数据性能好得多,但维护起来甚是困难,这个相比做过复杂crud页面的大佬们都深有体会,所以此时使用useReducer来统一管理,初始化父页面带入的参数,本页面统一控制state的变更,也能更方便的初始化页面state。
惰性初始化
此操作可以将用于计算 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> </> ); }
总结
useReducer作为hook里面state的替代方案,在需要的时候使用会提高页面执行效率,减少维护迭代开发时间,也能有效降低bug产生率,据阿里前端团队相关统计,页面使用useReducer比useState可以有效减少80%的bug,当然如果页面只有一两个state需要维护,此时可以根据个人习惯,快速使用useState来实现页面逻辑也是可以的。