React状态管理(〇)——或许你不需要状态管理库
众所周知,react可以抽象为一个函数:UI = render(data)
。这意味着我们可以专注于构建data,而不用考虑如何更新视图。
但随着SPA(single page application)单页面应用复杂度的提高,状态也会变大,管理状态的难度也会增加。
为了更好的管理应用的状态,或许会考虑状态使用react状态管理的库,但是该如何考虑和选择?
状态
首先我们要知道什么是状态,举个例子:当我们和我们的应用交互的时候,比如我们点击了一个button,会弹一个对话框,或者UI会有变化,或者发送一个请求。
随着点击事件,我们的应用有对应的响应。可以肯定的是这个时刻的状态跟点击之前的不一样了,我们应用进入了一个新的状态。比如说标志是否打开弹窗的变量、AJAX请求的数据,这些变量我们都可以称之为状态。
它可以是React中使用useState(函数组件)或者this.state(类组件)保存的数据,也可以保存第三方状态管理库里。
抉择
在React中如果我们需要储存状态,我们一般会选择一下三种途径方式:
- 储存在当前组件里面,函数组件里面可以使用useState、useReducer这些hooks,类组件可以存在this.state里面。
- 储存在第三状态管理库的仓库(store)里,相关的库有:Redux、MobX、Recoil...
- 自己维护状态,例如我们可以直接存在window里...
相应的如果改变状态,我们可以:
- 当我们调用useState、useReducer、this.setState的时候,React将会自动重新渲染,这是React提供给我们的机制。
- 如果我们使用第三方库,例如Redux、MobX、Recoil等。。。他们会在适当的时机,然后调用Ract的API触发重新渲染。
- 如果自己维护了数据,例如保存在window里,就需要自己实现状态改变触发重新渲染的逻辑,但是不建议。其实react并不在意你把数据放在哪,react处理的只是data -> UI的映射。
在绝大多数情况下,我们使用React提供的组件级别的状态管理API就完全足够了,也就是说或许你并不需要状态管理库。
简单状态共享场景
但是其实如果我们只用React提供的API,我们常常会遇到以下状态共享问题:
- prop drilling问题,即props传递的层级过深,我们需要手动传递props,比较麻烦。
- 树上距离较远的两个组件需要共享状态,在react中一个做法是,提取props到他们相邻最近的祖先节点中,回到第一种情况。
- 子组件向父组件传递数据,只能通过回调的方式。
造成这些问题的根本原因还是React的单向数据流的设计思想,React恨不得把所有状态都保存在顶层。
当然单向数据流的设计有利有弊,好处就是每个组件的依赖(数据流入)都很清晰,坏处就是状态共享问题。
于是,React提出了Context API。但是我们需要明确的是Context API解决的其实是依赖注入的问题,它本身并不是状态管理工具,具体可以看看这篇**Blogged Answers: Why React Context is Not a "State Management" Tool
事实上有基于Context API + Hooks封装库。
例如jamiebuilds/unstated-next等,他们的源码十分简单。
看过源码也就能发现,其实是会有性能问题的,更改状态后,所有使用context的组件都会重新渲染。所以他们只适用于需要快速上手、对性能要求不高的简单场景。
网络密集型的场景
这种场景常见于中后台项目,需要频繁从服务端请求数据,请求后的数据需需要进行加载状态、缓存和过期管理,这种场景可以使用React-query或者SWR。
以React-query特性来说:
- 使用hooks API
- 封装了许多前端异步请求的逻辑
- 数据缓存控制,自动更新数据
- 重复请求合并
- 分页和延迟加载
- ...
复杂场景
我觉得可能真正的复杂场景有:
- 用户的使用方式复杂
- 不同身份的用户有不同的使用方式(比如普通用户和管理员)
- 多个用户之间可以协作
- 与服务器大量交互,或者使用了WebSocket
- View要从多个来源获取数据
- ...
总而言之,在多状态、多交互、多数据源、数据耦合等复杂场景中,就需要使用复杂状态管理库。
按照设计思想,可以大概把他们分为四类:
- 单向数据流:Redux, Zustand
- 响应式数据流/Proxy:Mobx, Valtio
- 原子模式Atomic:Recoil, Jotai
- Stream: rxjs(Reactive Extension JavaScript)
这里要说一下Redux、Mobx等都是比较偏底层的并且是框架无关的,他们常常有框架关联的库如react-redux,mobx-react。
总结
在React生态里面,状态管理的库有很多,我们需要根据自己的需求选择适合业务场景的状态管理库。
接下来的文章将会介绍React里使用的比较多的几个主流状态管理库的主要思想和原理。
转载自:https://juejin.cn/post/7259182371974299704