React状态管理和Redux原理解析 | 青训营笔记

81 阅读3分钟

hooks和状态管理工具

类组件较为复杂,如果状态管理工具要兼容类组件,代码量会增加很多。

React官方提供的一些hooks会有助于状态管理工具的实现。

为什么React有这么多状态管理工具?

Vue、Anglar数据是双向绑定、计算属性等,数据响应式,需要状态管理的场景较少,此外本身包含了完整的状态管理工具,Vuex和Pinia,Angular的Service(Rxjs)等。

React是纯UI的框架,完全将状态的管理交给了开发者。

React的状态管理工具分类

  1. 自带:Local State和Context
  2. 单向数据流:Flux、Redux(Redux Toolkit)
  3. 双向数据绑定:Mobx
  4. 原子型状态管理:Recoil、Jotai
  5. 异步操作密集型:Rxjs

不同状态管理工具的特点和适用场景

  1. Local State

    1. 场景:嵌套层级不深
  2. Context

    1. createContext,useContext
    2. 无法进行细粒度更新,会穿透React.memo
    3. 使用context内部的组件耦合度太高
    4. 场景:全局配置,theme、language等;不同页面的相同属性。
  3. Redux

    1. 可回溯状态
    2. 样板代码多,中间件操作复杂
    3. 适用场景:大型项目
  4. Mobx

    1. 响应式、装饰器、直接修改状态
    2. 原子型,细粒度控制更新
    3. 代码风格很难统一
    4. 适用场景:数据流不太复杂的场景(但可以被useReducer和Recoil代替)

image.png

  1. Recoil

    1. 官方内置,兼容concurrent等新React新特性
    2. 原子粒度更新
    3. 状态快照,可用于填充首屏数据或数据状态回滚

image.png

  1. Zustand

    1. 轻量级,安装包不到1kB

    2. 初始化store时,同时初始化状态和改变状态的方法

    不要过度依赖状态管理工具

    实现一个简单的状态管理工具

    发布/订阅模式

image.png

image.png

Redux中间件原理

中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action -> middlewares -> reducer 。这种机制可以让我们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。

不同的中间件通过applyMiddleware串联,同时也要使用applyMiddleware将中间件应用到store上。

中间件其实是一个加工dispatch的工厂,每一个中间件函数接收dispatch函数,返回包装后的dispatch,并作为下一个中间件函数的next。

```
export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    //接收createStore参数
    var store = createStore(reducer, preloadedState, enhancer)
    var dispatch = store.dispatch
    var chain = []

    //传递给中间件的参数
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }

    //注册中间件调用链
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    //返回经middlewares增强后的createStore
    return {
      ...store,
      dispatch
    }
  }
}
```
  1. 返回一个函数,这个函数是一个增强版的createStore

  2. 怎么增强?从执行流程上来说,其实是依次执行中间件改造后的dispatch,然后执行store的原始dispatch。 从源码实现上,是分别得到改造后的dispatch,然后执行compose,实现中间件的依次执行。

    import {createStore,applyMiddleware} from 'redux';
    import reducers from './reducers/index';
    
    let createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);
    export let store = createStoreWithMiddleware(reducers);
    
    export default function thunkMiddleware({ dispatch, getState }) {
      return next => action =>
        typeof action === 'function' ?
          action(dispatch, getState) :
          next(action);
    }
    

    Redux connect api原理

    连接React组件和Redux Store

    实现原理:

    1. connect能够成功,是因为Provider组件,Provider组件接收store作为props,通过context对象传递给子孙组件上的connect。
    2. connect接收mapStateToProps、mapDispatchToProps,返回一个生产component的函数wrapWithConnect,再将真实的component作为参数传递给wrapWithConnect,最后返回一个经过包裹的组件。
    3. 这个组件获取祖先component的store props,将相应的props传递给真正的组件。
    4. 并且,这个组件,在didMount时,添加事件订阅store状态改变;shouldComponentUpdate判断是否需要渲染;willUnmount时卸载监听。