React 状态管理 | 青训营笔记

108 阅读5分钟

01什么是状态管理

从React诞生之后,前端组件化的方案深入人心,React遵循的是单向数据流的原则,属性通过Props自上而下的传递。当页面的比较简单,组件之间的层级关系比较浅时,这种自上而下的单向数据流的方式是不会有问题的。如果页面一复杂,组件的嵌套层级一深,这种单向数据流的传递方式,将会使你陷入到"嵌套地狱”

状态管理本身,解决的就是这种“嵌套”地狱的问题,解决的是跨层级组件之间的数据通信和状态共享

什么是状态管理

image.png

image.png

image.png

02 React状态管理简介

image.png

image.png

image.png 当然这种向上延伸的方法,不是无限的,如果一直往上延伸,会出现一个父组件嵌套10几层子组件的 情况,必须要有一个“度”,超过这个“度”后,我们就认为local State的方式就不太实用了。 这个“度”,在前端开发中,大部分情况下我们认为就是子页面。我们一般认为,单页应用中,子页面以 及子页面之下的组件都是可以用local State 来解决状态管理问题的,而子页面和子页面之间,是不需要再 往上延伸。那么子页面和子页面之间如何通信呢?
答案是:子页面和子页面之间的通信,React本身提供了 Context。

image.png

image.png

image.png

image.png

image.png

image.png Redux的三大原则:单一数据源,只有一个store、store中的state是只读的、使用纯函数来执行修改。
1.单一数据源: 在redux中,整个应用的全局State(再次注意是全局state).都会保存在一个store中,一个单一数据源 state tree 也简化了应用的调试和和监控;它也让你在开发中能将应用数据持久化到本地,从而加速开发周期。此外,有一些功能以前很难实现,比如“撤销/重做”,在单一数据源的原则下,使用 Redux 实现将非常容易。
2.store中的State是只读的: 我们不能直接修改store中的state,store中的state是只读的。唯一能改变store中的state的方式就是通过action
3.使用纯函数来执行修改: 接受纯函数来接受aciton,该纯函数叫reducer,可以改变store中的state.

因为Redux的上述特性,使得Redux可以做时间旅行。时间旅行:顾名思义,就是可以随时穿越到以前和未来让应用程序切换到任意时间的状态。因此,如果复杂的场景,特别是存在页面组件间复杂的通信的场景非常适合用 Redux来管理状态。

Redux 比较适合用于大型 Web 项目,尤其是一些交互足够复杂、组件通信频繁的场景,状态可预测和回溯是非常有价值的。还有一种场景,比如需要事故重现,这种定义和上报事故异常和重现的场景,Redux也很有意义。

Redux的缺点也很明显,首先为了实现纯函数的Reducer,Redux必须处理各种各样的副作用,需要引入一系列的副作用中间件,加重的心智负担,此外Action,Dispatch,Reducer的模式需要写过多的样版代码,虽然通过React hooks和Redux toolkit可以减少一定的样板代码,但是复杂度还是摆在那里。因此中小项目,也不太推荐使用Redux,可能Context或者React hooks中的useReducer就能满足你的需求。

image.png

Mobx 的优势在于上手简单,可以直接修改状态,不需要编写繁琐的 Action 和 Reducer,也不需要引入各 种复杂的中间件,局部精确更新,免去了粒度控制烦恼,自始至终一份引用,不需要 immutable,也没有复制对象的额外开销。因此前端数据流不太复杂的情况,使用 Mobx因为更加清晰,也便于维护。但是正是因为MobX的灵活,Mobx的代码风格很难统一。

不过Mobx是不能实现时间旅行和回溯的,因此不太适合前端数据流比较复杂的场景,此外,随着Reacthooks,比如useReducer等的,以及React自身的原子型状态管理工具Recoil。Mobx的使用场景会被进一步压缩目前的项目中使用Mobx的场景已经越来越小。

image.png

image.png

Recoil的核心,就是Atom原子状态,一集通过Atom原子状态可以派生出衍生状态Selector。

Recoil主要特点,就是较为官方,提供了与 Concurrent 模式及其他 React新特性兼容的可能性,主打的是性能。此外因为其原子性的特点,比较容易做到细粒度的状态控制。也能跟Redux实现状态回溯相比较Redux而言,还有一个特点就是理解起来没有很复杂,不需要写很多样板代码等。

Recoil还有一个特点就是可以实现状态快照。比如填充首屏数据和数据状态回滚等。

image.png

image.png

image.png

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

image.png

image.png

image.png

image.png

image.png

04 Redux在项目中的实践

image.png 在有副作用的action和原始的action之间增加中间件处理,从图中我们也可以看出,中间件的作用就是 转换异步操作,生成原始的action,这样,reducer函数就能处理相应的action,从而改变state,更新Ul。因为中间件,纯函数Reducer等使得Redux需要写很多样板代码,使用起来越来越复杂,早期我们使用redux-thunk,或者redux-saga等,但是复杂度还是在那里,因此在项目中不推荐使用如此复杂的Redux以及相关逻辑。

image.png

image.png