说到状态管理器,轮子满天飞。在 Class 时代,redux 与 mobx 几乎占据了全部市场,几乎没有没用过 redux 的同学。随着 Hooks 的诞生,新的一批轮子应运而生,其中有代表性的有 unstated-next、constate 等等。
当然无论什么轮子,要解决的问题都是一样的:**跨组件状态共享。**在解决这个核心问题的同时,需要尽可能的满足以下几个特性:

  • TypeScript 支持
  • 友好的异步支持
  • 支持状态互相依赖
  • 同时支持 Class 与 Hooks 组件
  • 使用简单

Recoil 体验

最近,facebook 官方出了一个状态管理器解决方案 Recoil,我们来体验一下。

准备工作

使用 Recoil,我们需要在项目最外层包一个 RecoilRoot ,这个和大部分状态管理器一致,通过 context 来跨组件传递数据。

import React from 'react';
import { RecoilRoot } from 'recoil';function App() {return (<RecoilRoot>...</RecoilRoot>);
}

跨组件状态共享

状态最简单的就是定义和使用。在 Recoil 中,通过 atom 来定义一个状态。

const inputValueState = atom({key: "inputValue",default: ""
});

如上面的代码所示,我们定义了一个 inputValue 状态,它的默认值是空字符串。
需要注意的是 key 字段,它应该是全局唯一的。这个 key 主要为了 debug 方便,持久化数据(数据恢复时的唯一标识),以及可以方便的看到全局 atoms 树。
消费状态也比较简单,通过 useRecoilState 来消费状态。

import React from "react";
import { useRecoilState } from "recoil";
import { inputValue } from "../store";const InputA = () => {const [value, setValue] = useRecoilState(inputValueState);return <input value={value} onChange={e => setValue(e.target.value)} />;
};export default InputA;

是不是很简单?Recoil 的基础用法就是这样的。我在这里写了一个 demo,你可以体验下。

状态互相依赖

有些状态需要依赖其它状态,这时候就要用 selector 来定义这个状态了。
比如,我们需要定义一个新的状态 filterdInputValue ,它是过滤 inputValue 中的数字后的值。

const filterdInputValue = selector({key: "filterdInputValue",get: ({get}) => {// 通过 get 可以读取其它状态const inputValue = get(inputValueState);return inputValue.replace(/[0-9]/ig, "");},
});

selector 比较简单,就是为了实现状态的依赖。你可以在这个 demo 体验下。

异步支持

良好的异步请求支持是状态管理器必不可少的。Recoil 提供了一个 useRecoilValueLoadable 来处理异步请求。直接上例子:

const currentUserNameQuery = selector({key: "CurrentUserName",get: async () => {const response = await queryUserInfo();return response.name;}
});

我们需要通过 selector 来定义异步状态,如果 get 函数是一个 Promise,则代表该状态为异步状态,需要使用 useRecoilValueLoadable 来消费该状态。

const UserName = () => {const userNameLoadable = useRecoilValueLoadable(currentUserNameQuery);switch (userNameLoadable.state) {case "hasValue":return <div>{userNameLoadable.contents}</div>;case "loading":return <div>Loading...</div>;case "hasError":throw userNameLoadable.contents;}
};

从上面例子可以看到, useRecoilValueLoadable 返回的状态,可以通过 state 字段读取到异步请求的状态。我写了个 demo,你可以体验下。

当然通过 useRecoilValueLoadable 来消费异步状态,比较符合我们当前的习惯。但 Recoil 更推荐通过 React.Suspense 来消费异步状态,这里就仁者见仁了,虽然 Suspense 可能是方向,但用起来是还不太习惯。

const UserName = () => {const userName = useRecoilValue(currentUserNameQuery);return <>{userName}</>}
};
function MyApp() {return (<React.Suspense fallback={<div>Loading...</div>}><UserName /></React.Suspense>);
}

评价

优点

  • 之前状态管理器满天飞,如果官方能一统天下,应该算一件好事情。
  • 对 React concurrent 模式支持良好。

不足

当前 Recoil 还处于开发阶段,文档都还不是很全。基于现状,说几点我的感受。

1. 没有使用 ts 实现,目前不支持 ts

这点我很惊讶,也是写这个文章的时候才发现的,很奇怪。讲道理 Recoil 支持 typescript 应该是顺手的事情,可能后期需要来个 @types/recoil 吧。

2. 目前没有支持 Class 组件消费状态。

这个特性应该是必备的,应该不会彻底抛弃 Class 组件。估计下个版本肯定会支持的这个特性的。实现成本较低,不支持的话就太反人类了。

3. API 偏多,有一定上手成本。

各类 API 一共有 19 个,偏复杂了。感觉很多都是可以合并的,比如 atomselector 合并成一个等等(也可能是我考虑不成熟)。建议官方可以考虑精简精简,本来是一个很简单的东西,搞的太复杂了。

4. 消费较繁琐

我们需要消费一个状态的时候,需要 import 两个东西,比较繁琐。

import { useRecoilState } from "recoil";
import { inputValueState } from "../store";// 用法
useRecoilState(inputValueState);

本来应该可以直接通过字符串 key 消费的,但这样和 redux 问题一样了,无法支持 ts。

import { useRecoilState } from "recoil";useRecoilState('inputValueState');

无论如果,import 两个东西不是一个好的用法。

5. 没有足够的亮点

没有看到让人眼前一亮的东西,没有使用冲动。静观发展~

后记

Recoil 整体看下来,比较中庸,需要静观发展。
另外推荐一下我目前正在用的最简单的 React 状态管理器 hox,只有一个 API,非常符合直觉,没有任何上手成本,完全拥抱 Hooks 。

❤️感谢大家

另外,我整了个公众号「前端技术砖家」,欢迎关注,大家一起共同交流和进步。

react全局状态管理_Recoil - Facebook 官方 React 状态管理器相关推荐

  1. react全局方法_前端面试题 ---react

    高阶组件相关 什么是高阶组件,它有哪些运用? 高阶组件就是一个函数,接收一个组件,经过处理后返回后的新的组件: 高阶组件,不是真正意义上的组件,其实是一种模式: 可以对逻辑代码进行抽离,或者添加某个共 ...

  2. react - redux 全局状态管理 、多组件共享状态 - 例子有详细注释

    react全局状态管理 基本概念 下面开始小例子 需要用到的插件redux 代码 - 代码中有详细的注释 参考 阮一峰的网络日志 先来看一下Redux的流程图 基本概念 Store: 保存数据的地方, ...

  3. react全局状态管理_react 状态管理的复杂度来源

    Ui = f(data) 本来按照这个公式,前端开发应该是非常愉悦的.最近发现有一些复杂度是因为现有的工具造成的,导致上面这个公式并不成立. 如果 data 不是一个浏览器的数据,而是数据库里的数据. ...

  4. flux react php,Vue的Flux框架之Vuex状态管理器

    学习vue之前,最重要是弄懂两个概念,一是"what",要理解vuex是什么:二是"why",要清楚为什么要用vuex. Vuex是什么? Vuex 类似 Re ...

  5. react大数据量渲染_React 中的状态自动保存(KeepAlive)

    什么是状态保存?假设有下述场景:移动端中,用户访问了一个列表页,上拉浏览列表页的过程中,随着滚动高度逐渐增加,数据也将采用触底分页加载的形式逐步增加,列表页浏览到某个位置,用户看到了感兴趣的项目,点击 ...

  6. 官方 React 快速上手脚手架 create-react-app

    此文简单讲解了官方 React 快速上手脚手架的安装与介绍. 1. React 快速上手脚手架 create-react-app 为了快速地进行构建使用 React 的项目,FaceBook 官方发布 ...

  7. uiswitchbutton 点击不改变状态_ES6专题—Generator与react状态机(14)

    大家在写App和一些单页面程序的时候,经常会遇到这样的情况: 当点击左边的箭头的时候,会出现灰黑色的抽屉效果,再点击一下向左的箭头,就会收起来,当然向右滑动和向左滑动也能实现抽屉效果的开关.还有,当抽 ...

  8. 关于FACEBOOK 的 REACT 专利许可证

    随着Apache.百度.Wordpress都在和Facebook的React.js以及其专利许可证划清界限,似乎大家又在讨论Facebook的这个BSD+PATENT的许可证问题了.这让我想起了之前在 ...

  9. web前端高级React - React从入门到进阶之组件的状态提升

    系列文章目录 第一章:React从入门到进阶之初识React 第一章:React从入门到进阶之JSX简介 第三章:React从入门到进阶之元素渲染 第四章:React从入门到进阶之JSX虚拟DOM渲染 ...

  10. 从Facebook的React框架事件学习一下开源协议

    前言 前一阵子由于Facebook BSD+PATENTS License的原因,Apache项目禁止使用带该license的代码,引人注目的就是Facebook的React前端框架. 后来在知乎上看 ...

最新文章

  1. 大脑认知能力获突破进展!《科学》发现促进大脑发育期间的关键细胞器
  2. php输出数据过大,PHPExcel导出数据量过大处理
  3. python文件传输socket_树莓派采用socket方式文件传输(python)
  4. 读取设置config.ini配置
  5. PMP资料,考过的学员整理分享
  6. 如何在桌面上显示我的计算机,Win10如何将我的电脑(此电脑)显示到桌面上?
  7. Ubuntu安装java的几种方式以及多个JAVA版本的切换
  8. 【SpringBoot】自定义starter实现详解
  9. Jmeter应用-接口测试
  10. 闲人博上介绍R语言的一篇好文章
  11. 开源网上商城程序(简介国内外开源网店系统)
  12. 【Keras】使用LSTM预测股票走势
  13. windows批处理脚本执行回到桌面的操作
  14. springboot毕业设计 基于springboot家教预约网站系统毕业设计设计与实现参考
  15. Libevent 学习七:Libevent 两个实例
  16. 同态加密能否拯救云计算
  17. 数学分析:据理说明为什么每一个含有第一类间断点的函数没有原函数
  18. python进行数据处理_用python进行数据分析(二:数据处理)
  19. U8 存货期初余额 货位
  20. 怎么将计算机桌面全部变成英文翻译,Word2010怎样将英文翻译成中文

热门文章

  1. 2、异常值(outliers)检测:业务法、Z-score、3σ准则、箱线图
  2. BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)
  3. 03-word 中插入图片和表格
  4. 成都拉升12名,长沙提升3位,最新全球城市排名出炉
  5. emv中的 部分匹配_EMV指标策略
  6. 相似度系列8:unify-BARTSCORE: Evaluating Generated Text as Text Generation
  7. 软件项目估算与计划不是一般的难
  8. 原滴滴副总裁叶杰平加盟贝壳找房,任首席科学家,用AI帮你找房
  9. Linux用户和组权限管理
  10. python 强类型 弱类型_Python 到底是强类型语言,还是弱类型语言?