React的Reducer Hook让state有了状态!
2023-03-20 14:51:24 时间
一、解决什么问题?
useReducer 是 useState 的升级版本,对 setState 这个操作进行了拆分,可以根据不同类型,进行不同的逻辑计算,最后去改变 state 对象。
1、实例:useReducer 实现计数器组件
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] = React.useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
);
}
二、useReducer 初始化方法
1、法一:使用第二个参数初始化
const [state, dispatch] = useReducer(
reducer,
{ count: initialCount }
);
2、法二:惰性初始化
useReducer 需要一个初始值和初始函数,经过计算得到的值作为 useReduccer 的初始化数据。这样就把计算逻辑独立在 useReducer 外部,为将来对重置 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 返回的 state 相比于之前没有变化,React会自动跳过对组件的渲染操作。这里的比较操作是调用了js的 Object.is()
方法。
四、解决层层回调的烦恼
1、useContext + useReducer
顶层组件有个回调函数要传递下去,需要每一层都使用 props 进行设置,很繁琐,这里可以用 useContext
+ useReducer
来解决。
useContext 负责传递执行函数,useReducer 负责对执行函数划分出不同状态,可供选择执行。
const TodosDispatch = React.createContext(null);
function TodosApp() {
// 提示:`dispatch` 不会在重新渲染之间变化
const [todos, dispatch] = useReducer(todosReducer);
return (
<TodosDispatch.Provider value={dispatch}>
<DeepTree todos={todos} />
</TodosDispatch.Provider>
);
}
function DeepChild(props) {
// 如果我们想要执行一个 action,我们可以从 context 中获取 dispatch。
const dispatch = useContext(TodosDispatch);
function handleClick() {
dispatch({ type: 'add', text: 'hello' });
}
return (
<button onClick={handleClick}>Add todo</button>
);
}
五、参考链接:
相关文章
- 金融服务领域的大数据:即时分析
- 影响大数据、机器学习和人工智能未来发展的8个因素
- 从0开始构建一个属于你自己的PHP框架
- 如何将Hadoop集成到工作流程中?这6个优秀实践必看
- SEO公司使用大数据优化其模型的5种方法
- 关于Web Workers你需要了解的七件事
- 深入理解HTTPS原理、过程与实践
- 增强分析:数据和分析的未来
- PHP协程实现过程详解
- AI专家:大数据知识图谱——实战经验总结
- 关于PHP的错误机制总结
- 利用数据分析量化协同过滤算法的两大常见难题
- 怎么做大数据工作流调度系统?大厂架构师一语点破!
- 2019大数据处理必备的十大工具,从Linux到架构师必修
- OpenCV中的KMeans算法介绍与应用
- 教大家如果搭建一套phpstorm+wamp+xdebug调试PHP的环境
- CentOS下三种PHP拓展安装方法
- Go语言HTTP Server源码分析
- Go语言HTTP Server源码分析
- 2017年4月编程语言排行榜:Hack首次进入前五十