亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747


深入Facebook 官方React 狀態(tài)管理器Recoil講解

 

作者: 磚家

轉(zhuǎn)發(fā)鏈接:https://mp.weixin.qq.com/s/cjwv25hSLBsUQ9m5De6vUg

前言

說到狀態(tài)管理器,輪子滿天飛。在 Class 時(shí)代,redux 與 mobox 幾乎占據(jù)了全部市場(chǎng),幾乎沒有沒用過 redux 的同學(xué)。隨著 Hooks 的誕生,新的一批輪子應(yīng)運(yùn)而生,其中有代表性的有 unstated-next、constate 等等。當(dāng)然無論什么輪子,要解決的問題都是一樣的:跨組件狀態(tài)共享。在解決這個(gè)核心問題的同時(shí),需要盡可能的滿足以下幾個(gè)特性:

  • TypeScript 支持
  • 友好的異步支持
  • 支持狀態(tài)互相依賴
  • 同時(shí)支持 Class 與 Hooks 組件
  • 使用簡(jiǎn)單

Recoil 體驗(yàn)

最近,facebook 官方出了一個(gè)狀態(tài)管理器解決方案 Recoil[1],我們來體驗(yàn)一下。

準(zhǔn)備工作

使用 Recoil,我們需要在項(xiàng)目最外層包一個(gè) RecoilRoot ,這個(gè)和大部分狀態(tài)管理器一致,通過 context 來跨組件傳遞數(shù)據(jù)。

import React from 'react';
import { RecoilRoot } from 'recoil';

function App() {
  return (
    <RecoilRoot>
        ...
    </RecoilRoot>
  );
}

 

跨組件狀態(tài)共享

狀態(tài)最簡(jiǎn)單的就是定義和使用。在 Recoil 中,通過 atom 來定義一個(gè)狀態(tài)。

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

如上面的代碼所示,我們定義了一個(gè) inputValue 狀態(tài),它的默認(rèn)值是空字符串。需要注意的是 key 字段,它應(yīng)該是全局唯一的。這個(gè) key 主要為了 debug 方便,持久化數(shù)據(jù)(數(shù)據(jù)恢復(fù)時(shí)的唯一標(biāo)識(shí)),以及可以方便的看到全局 atoms 樹。消費(fèi)狀態(tài)也比較簡(jiǎn)單,通過 useRecoilState 來消費(fèi)狀態(tài)。

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;

是不是很簡(jiǎn)單?Recoil 的基礎(chǔ)用法就是這樣的。我在這里寫了一個(gè) demo[2],你可以體驗(yàn)下。

狀態(tài)互相依賴

有些狀態(tài)需要依賴其它狀態(tài),這時(shí)候就要用 selector 來定義這個(gè)狀態(tài)了。比如,我們需要定義一個(gè)新的狀態(tài) filterdInputValue ,它是過濾 inputValue 中的數(shù)字后的值。

const filterdInputValue = selector({
  key: "filterdInputValue",
  get: ({get}) => {
    // 通過 get 可以讀取其它狀態(tài)
    const inputValue = get(inputValueState);
    return inputValue.replace(/[0-9]/ig, "");
  },
});

selector 比較簡(jiǎn)單,就是為了實(shí)現(xiàn)狀態(tài)的依賴。你可以在這個(gè) demo[3] 體驗(yàn)下。

異步支持

良好的異步請(qǐng)求支持是狀態(tài)管理器必不可少的。Recoil 提供了一個(gè) useRecoilValueLoadable 來處理異步請(qǐng)求。直接上例子:

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

我們需要通過 selector 來定義異步狀態(tài),如果 get 函數(shù)是一個(gè) Promise,則代表該狀態(tài)為異步狀態(tài),需要使用 useRecoilValueLoadable 來消費(fèi)該狀態(tài)。

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 返回的狀態(tài),可以通過 state 字段讀取到異步請(qǐng)求的狀態(tài)。我寫了個(gè) demo[4],你可以體驗(yàn)下。

深入Facebook 官方React 狀態(tài)管理器Recoil講解

 

當(dāng)然通過 useRecoilValueLoadable 來消費(fèi)異步狀態(tài),比較符合我們當(dāng)前的習(xí)慣。但 Recoil 更推薦通過 React.Suspense 來消費(fèi)異步狀態(tài),這里就仁者見仁了,雖然 Suspense 可能是方向,但用起來是還不太習(xí)慣。

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

 

評(píng)價(jià)

優(yōu)點(diǎn)

  • 之前狀態(tài)管理器滿天飛,如果官方能一統(tǒng)天下,應(yīng)該算一件好事情。
  • 對(duì) React concurrent 模式支持良好。

不足

當(dāng)前 Recoil 還處于開發(fā)階段,文檔都還不是很全。基于現(xiàn)狀,說幾點(diǎn)我的感受。

1. 沒有使用 ts 實(shí)現(xiàn),目前不支持 ts

這點(diǎn)我很驚訝,也是寫這個(gè)文章的時(shí)候才發(fā)現(xiàn)的,很奇怪。講道理 Recoil 支持 typescript 應(yīng)該是順手的事情,可能后期需要來個(gè) @types/recoil 吧。

2. 目前沒有支持 Class 組件消費(fèi)狀態(tài)。

這個(gè)特性應(yīng)該是必備的,應(yīng)該不會(huì)徹底拋棄 Class 組件。估計(jì)下個(gè)版本肯定會(huì)支持的這個(gè)特性的。實(shí)現(xiàn)成本較低,不支持的話就太反人類了。

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

深入Facebook 官方React 狀態(tài)管理器Recoil講解

 

各類 API 一共有 19 個(gè),偏復(fù)雜了。感覺很多都是可以合并的,比如 atom 和 selector 合并成一個(gè)等等(也可能是我考慮不成熟)。建議官方可以考慮精簡(jiǎn)精簡(jiǎn),本來是一個(gè)很簡(jiǎn)單的東西,搞的太復(fù)雜了。

4. 消費(fèi)較繁瑣

我們需要消費(fèi)一個(gè)狀態(tài)的時(shí)候,需要 import 兩個(gè)東西,比較繁瑣。

import { useRecoilState } from "recoil";
import { inputValueState } from "../store";

// 用法
useRecoilState(inputValueState);

本來應(yīng)該可以直接通過字符串 key 消費(fèi)的,但這樣和 redux 問題一樣了,無法支持 ts。

import { useRecoilState } from "recoil";

useRecoilState('inputValueState');

無論如果,import 兩個(gè)東西不是一個(gè)好的用法。

5. 沒有足夠的亮點(diǎn)

沒有看到讓人眼前一亮的東西,沒有使用沖動(dòng)。靜觀發(fā)展~

后記

Recoil 整體看下來,比較中庸,需要靜觀發(fā)展。另外推薦一下我目前正在用的最簡(jiǎn)單的 React 狀態(tài)管理器 hox[5],只有一個(gè) API,非常符合直覺,沒有任何上手成本,完全擁抱 Hooks 。

分享到:
標(biāo)簽:Facebook
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定