Recoil 是由 Facebook 推出的一个全新的、实验性的 JavaScript 状态管理库,它解决了使用现有 Context API 在构建大型应用时所面临的很多问题。
为什么使用 Recoil
在学一样东西之前,我们得了解它为什么会诞生,或者是它解决了什么问题。
Recoil 是由 Facebook 推出的一个全新的、实验性的 JavaScript 状态管理库,它解决了使用现有 Context API 在构建大型应用时所面临的很多问题。
使用 React 内置的状态管理能力有这样一些局限性:
- 组件间的状态共享只能通过将 state 提升至它们的公共祖先来实现,但这样做可能导致重新渲染一颗巨大的组件树。
- Context 只能存储单一值,无法存储多个各自拥有 Consumer 的值的集合。
- 以上两种方式都很难将组件树的顶层(state 必须存在的地方)与叶子组件 (使用 state 的地方) 进行代码分割。
尽管像 Redux 和 MobX 这样的库能够确保应用的状态保持一致,但是对于很多应用来讲,它们所带来的开销是难以估量的。
Redux、Mobx 本身并不是 React 库,我们是借助这些库的能力来实现状态管理。像 Redux 它本身虽然提供了强大的状态管理能力,但是使用的成本非常高,你还需要编写大量冗长的代码,另外像异步处理或缓存计算也不是这些库本身的能力,甚至需要借助其他的外部库。
并且,它们并不能访问 React 内部的调度程序,而 Recoil 在后台使用 React 本身的状态,在未来还能提供并发模式这样的能力
使用
先来看看 Recoil 是怎么使用的
根组件
使用 recoil 状态的组件需要使用 RecoilRoot 包裹起来,一般是根组件直接包裹
1 | import React from 'react' |
Atoms
Atom 是最小状态单元。它们可以被订阅和更新:当它更新时,所有订阅它的组件都会使用新数据重绘;它可以在运行时创建;它也可以在局部状态使用;同一个 Atom 可以被多个组件使用与共享。
相比 Redux 维护的全局 Store,Recoil 则是采用分散管理原子状态的设计模式,方便进行代码分割。
Atom 和传统的 state 不同,它可以被任何组件订阅,当一个 Atom 被更新时,每个被订阅的组件都会用新的值来重新渲染。
所以 Atom 相当于一组 state 的集合,改变一个 Atom 只会渲染特定的子组件,并不会让整个父组件重新渲染。
1 | import { atom } from 'recoil' |
要创建一个 Atom ,必须要提供一个 key ,其必须在 RecoilRoot 作用域中是唯一的,并且要提供一个默认值,默认值可以是一个静态值、函数甚至可以是一个异步函数。
API
Recoil 采用 Hooks 方式订阅和更新状态,常用的 API 如下:
useRecoilState
类似 useState 的一个 Hook,可以对 atom 进行读写
1 | import React, { useState } from 'react' |
useSetRecoilState
只获取 setter 函数,不会返回 state 的值,如果只使用了这个函数,状态变化不会导致组件重新渲染
1 | import React from 'react' |
useRecoilValue
只返回 state 的值,不提供修改方法
1 | import React from 'react' |
selector
selector 表示一段派生状态,它使我们能够建立依赖于其他 atom 的状态。它有一个强制性的 get 函数,其作用与 redux 的 reselect 或 MobX 的 computed 类似。
selector 是一个纯函数:对于给定的一组输入,它们应始终产生相同的结果(至少在应用程序的生命周期内)。这一点很重要,因为选择器可能会执行一次或多次,可能会重新启动并可能会被缓存。
1 | export const completeCountSelector = selector({ |
selector 还支持异步函数,可以将一个 Promise 作为返回值
结语
除了 Facebook,暂时还没有看到有哪些网站已经用了 Recoil。
Recoil 的核心概念都很简单,没有 Redux 那么绕的概念,也不需要写一堆像 action、reducer 之类的模板文件,基于 Hooks 的 API 以及它的直观性。与其他一些库相比,Recoil 的 API 比大多数库更容易,让开发更加简单。
我们现在的项目使用了 Recoil,目前感受是简化版的 Context API,使用较 Redux 简单,暂时没有发现能像 Redux 生态那样方便的时间回溯功能,后续使用有待继续观察。
- 个人技术博文 Github 仓库
觉得不错的话欢迎 star,给我一点鼓励继续写作吧~