教程 > Recoil.js 阅读:288

Recoil.js

使用 Recoil 会为你创建一个数据流向图,从 atom(共享状态)到 selector(纯函数),再流向 React 组件。Atom 是组件可以订阅的 state 单位。selector 可以同步或异步改变此 state

Recoil 定义了一个有向图 (directed graph),正交同时又天然连结于你的 React 树上。状态的变化从该图的顶点(我们称之为 atom)开始,流经纯函数 (我们称之为 selector) 再传入组件。

用于状态管理的 Recoil 数据流图
用于状态管理的 Recoil 数据流图


开发目的

出于兼容性和简便性的考虑,相比使用外部的全局状态,使用 React 内置的状态管理能力是个最佳的选择。但是 React 有这样一些局限性:

  • 组件间的状态共享只能通过将 state 提升至它们的公共祖先来实现,但这样做可能导致重新渲染一颗巨大的组件树。
  • Context 只能存储单一值,无法存储多个各自拥有消费者的值的集合。
  • 以上两种方式都很难将组件树的顶层(state 必须存在的地方)与叶子组件 (使用 state 的地方) 进行代码分割。

希望改善上述的问题的同时,不仅能保留 API 以及语义,还能使其的表现尽可能保持 React 的样子。

基于下面的实现,Recoil 诞生了

  • 可以定义无需模板代码的 API,共享的状态拥有与 React 本地 state 一样简单的 get/set 接口 (当然如果需要,也可以使用 reducer 等进行封装)。
  • 有了与 Concurrent 模式及其他 React 新特性兼容的可能性。
  • 状态的定义是渐进式和分布式的,这使代码分割成为可能。
  • 无需修改对应的组件,就能将它们本地的 state 用派生数据替换。
  • 无需修改对应的组件,就能将派生数据在同步与异步间切换。
  • 能将导航视为头等概念,甚至可以将状态的转变编码进链接中。
  • 可以很轻松地以可回溯的方式持久化整个应用的状态,持久化的状态不会因为应用的改变而丢失。

安装

NPM

Recoil 的 package 已上传至 npm。欲下载最新版本,请运行如下命令:

$ npm install recoil

或者可以使用 yarn:

$ yarn add recoil

Bundler

通过 npm 安装的 Recoil 与 Webpack 或 Rollup 等模块 bunlder 可以轻松匹配。

支持 ES5

Recoil 的构建没有转译成 ES5,我们也不支持在 ES5 下使用 Recoil。如果你需要兼容不支持 ES6 的浏览器,你可以通过 Babel 编译你的代码,并使用 @babel/preset-env 的 preset。然而,我们不建议你这样做,你可能会遇到问题。

主要是,像 React 这类的库,Recoil 依赖于 Map 和 Set 类型以及其他 ES6 的特性。使用 polyfill 来模拟这些特性可能会导致性能大大降低。

CDN

从 0.0.11 版本开始,Recoil 提供了 UMD 构建,可以直接在 <script> 中使用,并将符号 Recoil 暴露给全局的命名空间。我们建议链接到一个特定的版本号和构建,以避免较新版本带来的破坏性更改:

<script src="https://cdn.jsdelivr.net/npm/recoil@0.0.11/umd/recoil.production.js"></script>

你可以浏览 jsdelivr CDN 上所有的 Recoil 文件。

ESLint

如果你在你的项目中使用了 eslint-plugin-react-hooks。例如,在 eslint 中的配置如下:

// previous .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

建议将 'useRecoilCallback' 添加到 additionalHooks 列表中。这样做,当传递给 useRecoilCallback() 的依赖关系出错时,ESLint 会发出警告,并建议进行修复。additionalHooks 的格式是一个 regex 字符串。

// modified .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": [
      "warn", {
        "additionalHooks": "useRecoilCallback"
      }
    ]
  }
}

查看笔记

扫码一下
查看教程更方便