useReducer
?首先我们来聊聊什么是 useReducer ?官方文档是这么解释的:
An alternative to useState. Accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. (If you’re familiar with Redux, you already know how this works.)
useState
useState
其实和 useReducer
很相似,只不过 useReducer
是一个升级版,两者同样都是用来存储和更新数据局状态,但是 useReducer
能处理更复杂的逻辑,以下是使用两种用法达到同样效果的例子。
useState
useReducer
学过 Redux 的可以很轻松上手,核心的概念和思想是一模一样的:Action、Reducer、Store。
useReducer
示意图接下来我们看一个简单的代码示意,点击按钮计数器+1,看完这个我们看看是如何使用的:
const { useState, useReducer } = React; const ACTIONS = { INCREMENT: 'increament', DECREMENT: 'decreament' } function reducer(state, action) { switch(action.type) { case ACTIONS.INCREMENT: return { count: state.count + 1} case ACTIONS.DECREMENT: return { count: state.count - 1} default: return state } } const Counter = () => { const [state, dispatch] = useReducer(reducer, {count: 256}) const increase = () => { dispatch({type: ACTIONS.INCREMENT}) }; const decrease = () => {dispatch({type: ACTIONS.DECREMENT }) }; return ( <div> <button onClick={decrease} /> <span>{state.count}</span> <button onClick={increase} /> </div> ) };
从上述代码我们可以看出 useReducer 的基础用法
接下来我们通过一个实例来深入学习理解下 useReducer
,示例效果如下图所示:
接下来我们来分析这个简单示例的需求:
Modal
提示层组件首先我们从最简单的组件开始,定义一个 Modal
的提示层,用来对用户的输入信息进行反馈,比如“人员添加成功”,“请输入人员信”。此组件有两个属性 modalContent
(提示文字)和 closeModal
(关闭弹出层事件),Modal.js 文件如下:
import React, { useEffect } from 'react'; const Modal = ({ modalContent, closeModal }) => { useEffect(() => { setTimeout(() => { closeModal(); }, 3000); }); return ( <div className='modal'> <p>{modalContent}</p> </div> ); }; export default Modal;
Index
页面组件定义 Index
组件,包含了 输入框和提示按钮,初始化数据状态 defaultState
,包含三个对象属性:people
(用户数据) 、isModalOpen
(用于是否显示提示信息)、modalContent
(提示信息内容)、同时定义了很关键的 useReducer
,通过不同的 type 类型进行数据的添加和删除人员信息,相关的示例代码如下:
import React, { useState, useReducer } from 'react'; import Modal from './Modal'; import { reducer } from './reducer'; const defaultState = { people: [], isModalOpen: false, modalContent: '', }; const Index = () => { const [name, setName] = useState(''); const [state, dispatch] = useReducer(reducer, defaultState); const handleSubmit = (e) => { e.preventDefault(); if (name) { const newItem = { id: new Date().getTime().toString(), name }; dispatch({ type: 'ADD_ITEM', payload: newItem }); setName(''); } else { dispatch({ type: 'NO_VALUE' }); } }; const closeModal = () => { dispatch({ type: 'CLOSE_MODAL' }); }; return ( <> {state.isModalOpen && ( <Modal closeModal={closeModal} modalContent={state.modalContent} /> )} <form onSubmit={handleSubmit} className='form'> <div> <input type='text' value={name} onChange={(e) => setName(e.target.value)} /> </div> <button type='submit'>添加</button> </form> {state.people.map((person) => { return ( <div key={person.id} className='item'> <h4>{person.name}</h4> <button onClick={() => dispatch({ type: 'REMOVE_ITEM', payload: person.id }) } > 删除 </button> </div> ); })} </> ); }; export default Index;
useReducer
操作useReducer
文件是核心部分,在这里我们定义相关的核心操作,例如添加、删除等操作,示例代码如下:
export const reducer = (state, action) => { if (action.type === 'ADD_ITEM') { const newPeople = [...state.people, action.payload]; return { ...state, people: newPeople, isModalOpen: true, modalContent: '人员添加成功', }; } if (action.type === 'NO_VALUE') { return { ...state, isModalOpen: true, modalContent: '请输入人员信息' }; } if (action.type === 'CLOSE_MODAL') { return { ...state, isModalOpen: false }; } if (action.type === 'REMOVE_ITEM') { const newPeople = state.people.filter( (person) => person.id !== action.payload ); return { ...state, people: newPeople }; } throw new Error('没有匹配的操作'); };
到这里关于本案例就介绍完了,关于 useReducer
是不是很容易理解呢。
关于 useReducer
的使用总结就介绍到这里,实际上有许多情况直接用 useState
会比要建一个 useReducer
更简单,因为 useReducer
的使用方法是希望我们用像redux 的方式来管理状态,透过 action -> reducer -> store
的方式管理状态流。你应该不会想在一个简单的component 写一堆reducer 的代码,不然后续维护时你会后悔死。但是有些情况 useReducer
会比 useState
更好用,会写出更容易维护的程式码,在一些复杂的业务逻辑场景,建议使用 useReducer
。有句题外话,React 的官方网站也提到 useReducer
是 useState
的一种替代性写法,让我们以为它们是不同的东西,但是谁知道 useState
的底层其实是用 useReducer
做的呢😜。
注:本文属于原创文章,版权属于「前端达人」公众号及 qianduandaren.com 所有,未经授权,谢绝一切形式的转载