react全局状态管理_深入Facebook 官方React 状态管理器Recoil讲解

react全局状态管理_深入Facebook 官方React 状态管理器Recoil讲解_第1张图片

作者: 砖家

转发链接:https://mp.weixin.qq.com/s/cjwv25hSLBsUQ9m5De6vUg

前言

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

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

Recoil 体验

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

准备工作

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

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

跨组件状态共享

状态最简单的就是定义和使用。在 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  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 
{userNameLoadable.contents}
;    case "loading":      return 
Loading...
;    case "hasError":      throw userNameLoadable.contents;  }};

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

react全局状态管理_深入Facebook 官方React 状态管理器Recoil讲解_第2张图片

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

const UserName = () => {  const userName = useRecoilValue(currentUserNameQuery);  return <>{userName}> }};function MyApp() {  return (    Loading...
}>      

你可能感兴趣的:(react全局状态管理)