对于 React ,你可能不需要状态管理
点击上方“前端技术砖家”关注
提到状态管理,可能大多数人的第一反应就是 redux、dva、mobx,可是随着时间的推移,React 的能力不断增强,前端的工程化日益成熟,应用的形态渐渐复杂,如今,或许我们应该重新审视一下,什么是状态管理,又如何做好状态管理。
状态管理的本质是什么社区中对 React 状态管理方案的讨论从未停息过,特别是自从 Hooks 诞生以来,各种“新颖”的状态管理方案层出不穷,为了能更理性的看待这个问题,我们不妨把那些具体的框架/库都抛在脑后,先来聊一聊,抽象层面上的“状态管理”到底意味着什么。
❝给一个抽象的东西下定义,是非常难的。例如我们在讨论“书是什么”时,有些人可能会认为书就是纸张构成的一本印刷册,可有的人认为手写的一本稿子也算是书,而又有的人会认为电子产品中的一部文字的集合也算是广义上的书。空谈概念的定义是没有什么意义的,很多概念的边界是模糊的,与其浪费时间去争出一个大家都认同的“边界”,不如先找出一个粗略的定义,毕竟我们只是想借助对定义的探讨,来反观现实。
❞
在我个人的观念里,状态管理主要有两个方面的职能:
- 「数据的共享」
在 React 应用中,在组件间优雅的共享一些数据并非易事,而各种状态管理工具都给出了自己对“数据共享”的标准方案 - 「逻辑的组织」
状态不单单是数据项的堆砌,更重要的是把各项数据之间的逻辑、数据与其他系统模块之间的互动逻辑进行组织,例如 A 需要在用户点击按钮时发生变化,而 B 又需要在 A 变化时跟着变化(可能是同步的也可能是异步的)
不知道这是不是 redux 或 mobx 的初衷,但这确实是我一直以来对状态管理工具的“「痛点需求」”。
那么接下来,我们不妨在这两个方面分别讨论:
既然要共享数据,那么最简单粗暴的方案就是直接做成「全局」性的(redux 也确实是这么做的),于是很多人的都渐渐形成了一种认知:React 应用中的状态有两种,一种是组件内部的(this.state / useState),另一种是全局的(redux)。但是,「内部状态」的反义词从来都不是「全局状态」,而是「共享状态」,全局只是共享的一种途径罢了,并不能成为其本身。
目前来看,在组件间进行状态的共享,有两种比较可靠的途径,其一就是刚刚提到的「全局状态共享」,而另一种,也是我个人更加倾向的,是「局部状态共享」。React 提供了非常简洁易用的 Context API,用于在一个组件树中共享数据,局部状态共享的思路大致就是来自于此,在一个组件树(而非整个应用)内进行数据共享。
可是这样做又能有什么好处呢?
- 「自治」
一个组件树可以完成逻辑的封闭,减轻对全局的依赖和干扰,甚至还对组件的封装非常有益 - 「多例」
局部共享的状态也可以像组件(树)一样拥有多例的能力,可以打破全局单例对很多逻辑场景的限制 - 「生命周期」
局部状态跟随组件树创建和销毁,干净而且易于维护,最常见的场景是让共享状态的生命周期和页面的生命周期保持同步
当然,反对的声音也是存在的:
- 「不够规范」
局部状态满天飞,容易让逻辑变乱,排查问题也会变得非常困难 - 「需要一定的认知成本」
局部状态不如全局状态那么直观,虽然灵活但也增加了使用成本
其实大家不难发现,局部状态中“局部”是可大可小的,不论是小至包裹在一个组件外面(虽然不会有人真的这样写代码),还是包裹到整个应用外面,都可以称之为“局部”。因此准确的讲,全局状态只是局部状态的一个「子集」、一个「特例」。局部状态这种模式,只是把枷锁解掉了,并非和全局状态互斥。
逻辑组织:Hooks 究竟改变了什么?我觉得状态管理中真正的痛点在于“和数据相粘连的逻辑”如何组织,而 Hooks 提供了一整套完备的管理逻辑的方案,从状态到副作用到性能优化到异步。
在以前,对于组件内部的状态,逻辑组织能力是非常薄弱的,因此很多人求助于把状态抽到外部(例如 redux),因为外部的状态管理器中可以更好的组织业务逻辑。甚至更极端的,会试图把整个应用状态都放在 redux 中,而 React 组件内不允许保留状态。
但是 Hooks 的诞生让组件内部状态的逻辑组织能力得到了大幅提升,我觉得是完全不输甚至更强于 flux 模式的。如果我们能够把组件内部状态和共享状态全部都用 Hooks 进行组织,那我们就再也不需要对一份数据该存放在哪里而感到纠结了,因为我们只需要关心一点:这份数据被谁需要了?是只有这个组件自己,还是多个组件之间?
Hooks 不是为了状态管理而生的,但却可以深刻地改变整个生态。就像智能手机不是为了购物而生的,但却可以颠覆人们的消费和生活方式。
状态管理之所以一直以来被人们特意强调,一定程度上恰恰是因为它的格格不入,需要被人们去单独学习和特别注意。如果大胆猜测一下的话,我会觉得在不久的将来,我们之前热衷于讨论的“状态管理”这个词,会更多的意味着“状态共享”,甚至于销声匿迹。一个 React 应用的状态构成也会从“组件内的状态 + 状态管理器中的状态”变成“组件内的状态+组件间共享的状态”。
❝「写在最后」作为一名经验绝对算不上丰富的前端,写这篇文章确实花费了我很大的勇气,文中难免有所偏颇和疏漏,还请读者朋友多多包涵,若是能给大家带来一点帮助,那真的是非常荣幸。
❞
推荐阅读
我的公众号能带来什么价值?(文末有送书规则,一定要看)
每个前端工程师都应该了解的图片知识(长文建议收藏)
为什么现在面试总是面试造火箭?
在看点这里