Redux思想

image.png
我们的应用中,每个组件都有自己的 State(状态)和 State Setter(状态修改函数),这意味着跨组件的状态读取和修改是相当麻烦的。而 Redux 的核心思想之一就是将状态放到唯一的全局对象(一般称为 Store)中,而修改状态则是调用对应的 Reducer 函数去更新 Store 中的状态,大概就像这样:
v2-48b7b0064270aa663972f774dfdd3917_b.gif

上面这个动画描述的是组件 A 改变 B 和 C 中状态的过程:

  • 三个组件挂载时,从 Store 中获取并订阅相应的状态数据并展示(注意是只读的,不能直接修改)
  • 用户点击组件 A,触发事件监听函数
  • 监听函数中派发(Dispatch)对应的动作(Action),传入 Reducer 函数
  • Reducer 函数返回更新后的状态,并以此更新 Store
  • 由于组件 B 和 C 订阅了 Store 的状态,所以重新获取更新后的状态并调整 UI

useReducer+useContext模拟

我们知道,useReducer是用来处理复杂状态维护的,useContext是用来处理嵌套层级深的时候数据传递
二者结合 来模拟Redux吧

  1. 定义reducer,initialState
  2. 创建context
  3. 向下传递context
  4. 子组件dispatch触发状态改变
  1. // 1. 定义reducer和初始值
  2. const basInfoState = {
  3. prCode: '',
  4. budgetCode: '', // 立项单号
  5. prHeadFileList: [], // 供应商附件
  6. requestType: 'NORMAL', // 申请类型
  7. relationCode: null, // 关联立项/采购申请单号
  8. purposeKpi: '', // 申请目的及KPI
  9. description: '', // 申请描述
  10. prName: '', // 申请单名称
  11. isAutoLocateInvalid: true, // 引导前form验证不追踪,引导后追踪
  12. prGuideIsShowing: false, // pr用户引导是否为正在展示
  13. };
  14. function baseInfoReducer(state, action) {
  15. switch (action.type) {
  16. case 'INIT_BASE_FORM':
  17. return { ...state, ...action.payload };
  18. default:
  19. return state;
  20. }
  21. }
  22. export { baseInfoReducer, basInfoState };
  23. -----------------------------------------------
  24. // 2. 创建context
  25. const RequestContext = createContext();
  26. const [baseInfoState, dispatchBaseInfo] = useReducer(baseInfoReducer, basInfoState);
  27. // 3. 将dispatch和state向下传递
  28. return (
  29. <RequestContext.Provider
  30. value={{
  31. baseInfoState,
  32. dispatchBaseInfo,
  33. }}
  34. >
  35. <Loading loading={loading}>
  36. ...
  37. </Loading>
  38. </RequestContext.Provider>
  39. );
  40. ---------------------------------------------
  41. // 4. 触发dispatch
  42. import { RequestContext } from '...';
  43. const {
  44. baseInfoState: baseForm,
  45. dispatchBaseInfo,
  46. } = useContext(RequestContext);
  47. ....
  48. const handleFillBaseForm = (e)=>{
  49. dispatchBaseInfo({ type: 'INIT_BASE_FORM', payload: { purposeKpi: e.target.value } });
  50. }

这种结合的方式和Redux有什么区别呢?应该作何取舍呢?
Redux更像是集中将全力赋给Store
useReducer+useContext这种更像是给每个子组件赋予了context的权利

References

https://github.com/puxiao/react-hook-tutorial/blob/master/09%20useReducer%E9%AB%98%E7%BA%A7%E7%94%A8%E6%B3%95.md