文章插图
作者: 砖家
【深入Facebook 官方React 状态管理器Recoil讲解】转发链接:https://mp.weixin.qq.com/s/cjwv25hSLBsUQ9m5De6vUg
前言说到状态管理器,轮子满天飞 。在 Class 时代,redux 与 mobox 几乎占据了全部市场,几乎没有没用过 redux 的同学 。随着 Hooks 的诞生,新的一批轮子应运而生,其中有代表性的有 unstated-next、constate 等等 。当然无论什么轮子,要解决的问题都是一样的:跨组件状态共享 。在解决这个核心问题的同时,需要尽可能的满足以下几个特性:
- TypeScript 支持
- 友好的异步支持
- 支持状态互相依赖
- 同时支持 Class 与 Hooks 组件
- 使用简单
准备工作使用 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=https://www.isolves.com/it/cxkf/bk/2020-05-20/{value} onChange={e => setValue(e.target.value)} />;};export default InputA;
是不是很简单?Recoil 的基础用法就是这样的 。我在这里写了一个 demo[2],你可以体验下 。状态互相依赖有些状态需要依赖其它状态,这时候就要用 selector 来定义这个状态了 。比如,我们需要定义一个新的状态 filterdInputValue,它是过滤 inputValue 中的数字后的值 。
const filterdInputValue = selector({ key: "filterdInputValue", get: ({get}) => { // 通过 get 可以读取其它状态 const inputValue = get(inputValueState); return inputValue.replace(/[0-9]/ig, ""); },});
selector 比较简单,就是为了实现状态的依赖 。你可以在这个 demo[3] 体验下 。异步支持良好的异步请求支持是状态管理器必不可少的 。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[4],你可以体验下 。
推荐阅读
- 深入浅出Spring/SpringBoot 事件监听机制
- 汽车|油价大降!加满一箱油将少花21.5元 会继续降吗?官方回应
- 深入理解PHP+Mysql分布式事务与解决方案
- 天文航天|英雄回家!官方:神舟十三号即将撤离空间站
- 店侦探淘宝官方下载 淘宝店侦探手机版下载
- 官方淘宝收藏大师有用吗 淘宝怎么样收藏店铺
- 淘宝怎样安装店侦探 店侦探淘宝官方下载
- 生意参谋官方入口 生意参谋网页版
- 深入浅出为什么你的网页需要CSP?【前端篇】
- 架构师修炼之微服务部署 - 深入理解Docker镜像