Redux思想
我们的应用中,每个组件都有自己的 State(状态)和 State Setter(状态修改函数),这意味着跨组件的状态读取和修改是相当麻烦的。而 Redux 的核心思想之一就是将状态放到唯一的全局对象(一般称为 Store)中,而修改状态则是调用对应的 Reducer 函数去更新 Store 中的状态,大概就像这样:
上面这个动画描述的是组件 A 改变 B 和 C 中状态的过程:
- 三个组件挂载时,从 Store 中获取并订阅相应的状态数据并展示(注意是只读的,不能直接修改)
- 用户点击组件 A,触发事件监听函数
- 监听函数中派发(Dispatch)对应的动作(Action),传入 Reducer 函数
- Reducer 函数返回更新后的状态,并以此更新 Store
- 由于组件 B 和 C 订阅了 Store 的状态,所以重新获取更新后的状态并调整 UI
useReducer+useContext模拟
我们知道,useReducer是用来处理复杂状态维护的,useContext是用来处理嵌套层级深的时候数据传递
二者结合 来模拟Redux吧
- 定义reducer,initialState
- 创建context
- 向下传递context
- 子组件dispatch触发状态改变
// 1. 定义reducer和初始值
const basInfoState = {
prCode: '',
budgetCode: '', // 立项单号
prHeadFileList: [], // 供应商附件
requestType: 'NORMAL', // 申请类型
relationCode: null, // 关联立项/采购申请单号
purposeKpi: '', // 申请目的及KPI
description: '', // 申请描述
prName: '', // 申请单名称
isAutoLocateInvalid: true, // 引导前form验证不追踪,引导后追踪
prGuideIsShowing: false, // pr用户引导是否为正在展示
};
function baseInfoReducer(state, action) {
switch (action.type) {
case 'INIT_BASE_FORM':
return { ...state, ...action.payload };
default:
return state;
}
}
export { baseInfoReducer, basInfoState };
-----------------------------------------------
// 2. 创建context
const RequestContext = createContext();
const [baseInfoState, dispatchBaseInfo] = useReducer(baseInfoReducer, basInfoState);
// 3. 将dispatch和state向下传递
return (
<RequestContext.Provider
value={{
baseInfoState,
dispatchBaseInfo,
}}
>
<Loading loading={loading}>
...
</Loading>
</RequestContext.Provider>
);
---------------------------------------------
// 4. 触发dispatch
import { RequestContext } from '...';
const {
baseInfoState: baseForm,
dispatchBaseInfo,
} = useContext(RequestContext);
....
const handleFillBaseForm = (e)=>{
dispatchBaseInfo({ type: 'INIT_BASE_FORM', payload: { purposeKpi: e.target.value } });
}
这种结合的方式和Redux有什么区别呢?应该作何取舍呢?
Redux更像是集中将全力赋给Store
useReducer+useContext这种更像是给每个子组件赋予了context的权利