hooks和状态管理工具
类组件较为复杂,如果状态管理工具要兼容类组件,代码量会增加很多。
React官方提供的一些hooks会有助于状态管理工具的实现。
为什么React有这么多状态管理工具?
Vue、Anglar数据是双向绑定、计算属性等,数据响应式,需要状态管理的场景较少,此外本身包含了完整的状态管理工具,Vuex和Pinia,Angular的Service(Rxjs)等。
React是纯UI的框架,完全将状态的管理交给了开发者。
React的状态管理工具分类
- 自带:Local State和Context
- 单向数据流:Flux、Redux(Redux Toolkit)
- 双向数据绑定:Mobx
- 原子型状态管理:Recoil、Jotai
- 异步操作密集型:Rxjs
不同状态管理工具的特点和适用场景
-
Local State
- 场景:嵌套层级不深
-
Context
- createContext,useContext
- 无法进行细粒度更新,会穿透React.memo
- 使用context内部的组件耦合度太高
- 场景:全局配置,theme、language等;不同页面的相同属性。
-
Redux
- 可回溯状态
- 样板代码多,中间件操作复杂
- 适用场景:大型项目
-
Mobx
- 响应式、装饰器、直接修改状态
- 原子型,细粒度控制更新
- 代码风格很难统一
- 适用场景:数据流不太复杂的场景(但可以被useReducer和Recoil代替)
-
Recoil
- 官方内置,兼容concurrent等新React新特性
- 原子粒度更新
- 状态快照,可用于填充首屏数据或数据状态回滚
-
Zustand
-
轻量级,安装包不到1kB
-
初始化store时,同时初始化状态和改变状态的方法
不要过度依赖状态管理工具
实现一个简单的状态管理工具
发布/订阅模式
-
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
}
}
}
```
-
返回一个函数,这个函数是一个增强版的createStore
-
怎么增强?从执行流程上来说,其实是依次执行中间件改造后的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
实现原理:
- connect能够成功,是因为Provider组件,Provider组件接收store作为props,通过context对象传递给子孙组件上的connect。
- connect接收mapStateToProps、mapDispatchToProps,返回一个生产component的函数wrapWithConnect,再将真实的component作为参数传递给wrapWithConnect,最后返回一个经过包裹的组件。
- 这个组件获取祖先component的store props,将相应的props传递给真正的组件。
- 并且,这个组件,在didMount时,添加事件订阅store状态改变;shouldComponentUpdate判断是否需要渲染;willUnmount时卸载监听。