关于前端:Recoil入门

94次阅读

共计 3468 个字符,预计需要花费 9 分钟才能阅读完成。

Recoil 作为在《React Europe 2020 Conference》上,Facebook 外部释出的状态治理库,我想很多人对此都是充斥趣味的,所以花了几天工夫整顿了一些材料,做个入门分享。上面次要以Why Recoil -> When Recoil -> How Recoil 的程序去介绍 Recoil。

1.Why Recoil

它为什么呈现呢?
问题的源头能够追溯到 React 框架自身,因为 React 规定了数据的流向是由外层组件向内层组件进行传递和更新,组件状态只能与其先人组件进行共享,这可能会带来组件树中大量的重绘开销,组件间通信也会很不不便。

尽管 Context 能够解决这种问题,然而 Context 的问题在于:

Context can only store a single value, not an indefinite set of values each with its own consumers.(Context 只能保留一个特定值而不是与其 Consumer 共享一组不确定的值)

这会导致组件树顶部组件(状态生产者)与组件树底部组件(状态消费者)之间的代码拆分变得十分艰难。

以上是官网文档给出的解释,第一次看到时候我是这样的😵。细品之后,感觉它想表白的意思其实是:
1. 首先明确 Context 工作机制:因为每当 Provider 的值产生扭转时, 作为 Provider 后辈的所有 Consumers 都会从新渲染。
2. 当存在多个 Consumer 时,为了防止不必要的更新,不会把所有 Consumers 用到的状态都一股脑塞进同一个Provider
3. 所以就呈现了多个Provider-Consumer,为的就是各自治理各自的状态,互不打搅。
4. 然而这就呈现了另一个问题:代码耦合,拆分艰难。(完结撒花🌸)

言归正传,以上这些问题促成了 Recoil 的诞生,同时为了达到高性能的目标,须要更加精密地操作数据流,最初 Recoil 打算通过不同于 redux、mobx 的形式解决这些问题:

  • Flexible shared state: 在 react tree 任意的中央都能灵便共享 state,并放弃高性能
  • Derived data and queries: 高效牢靠地依据变动的 state 进行计算
  • App-wide state observation: time travel debugging, 反对 undo, 日志长久化

Recoil 就这样诞生了🐣🐣🐣🐣🐣🐣🐣

2.When Recoil

咱们什么时候应用它呢?

比拟现有的状态库reduxmobx,它们的区别次要在于:

状态治理库 Redux Mobx Recoil
流程 标准 / 简单 自在 / 简略 标准 / 简略
依赖 redux/react-redux/redux-saga mobx/mobx-react recoil
反对 类 / 函数组件 类 / 函数组件 函数组件
学习老本
思维 函数式 响应式 hook
版本 正式 正式 测试

所以基于以上剖析,我的项目在满足 React 我的项目 && 应用 hook && 小型我的项目 的时候,咱们能够思考应用 Recoil。

3.How Recoil

Recoil 是如何实现状态治理的呢?

让咱们看看,Recoil为了达到 Flexible shared stateDerived data and queries 这两个目标具体是怎么做的😊。

Shared state

有一个利用基于这样一个场景,将 List 中更新一个节点,而后对应 Canvas 中的节点也更新

Recoil采纳的形式是在 React Tree 上创立另一个正交的 Tree,把每个节点的 state 抽出来。每个 component 都有对应独自的一片 state,当数据更新的时候对应的组件也会更新。Recoil 把 这每一片的数据称为 Atom,Atom 是可订阅可变的 state 单元。如图所示:

Derived Data

有这么一个场景须要依据 List 计算 totalNum、totalCompletedNum 之类基于 List 的 派生状态

这是不是有点 Mobx中的 @computed 那味儿了🤨,Derived Data 的具体思路是选取多个 Atom 进行计算,而后返回一个新的 state。因而在 Recoil 中设计了 selector 这样的 API 来选取多个 Atom 进行计算。selector 的设计和 Proxy 挺像的,属性上有 get 进行读取,有 set 进行设置,函数外部又有 get,set 操作 state。

那咱们如何应用它呢?

间接实际一个 demo 吧,然而写 demo 之前最好先理解几点重要的概念:

  • 相似于 Provider 应用Recoil 须要在根节点里面包裹一层<RecoilRoot/>
  • Atom 代表状态、Selector 代表 派生状态
  • 罕用的 hook 函数有 useRecoilValueuseSetRecoilStateuseRecoilState

这里粘几行 useRecoilState 的源码,置信大家就晓得这三个 hook 大略的用处了:

function useRecoilState<T>(recoilState: RecoilState<T>,): [T, SetterOrUpdater<T>] {if (__DEV__) {// $FlowFixMe[escaped-generic]
    validateRecoilValue(recoilState, 'useRecoilState');
  }
  return [useRecoilValue(recoilState), useSetRecoilState(recoilState)];
}

上面实现一个官网的繁难 demo:
查看 demo

//App.js
import React from 'react';
import {RecoilRoot} from 'recoil';
import CharacterCounter from './pages/charCounter'

export default function App() {
  return (
    <RecoilRoot>
      <CharacterCounter />
    </RecoilRoot>
  );
}
//charCounter.js
import {useRecoilState, useRecoilValue} from 'recoil'
import {textState, charCountState} from '../store/charCounterStore'

export default function CharacterCounter() {
    return (
        <div>
            <TextInput />
            <CharacterCount />
        </div>
    );
}

function TextInput() {const [text, setText] = useRecoilState(textState);
    const onChange = (e) => setText(e.target.value);
    return (
        <div>
            <input type="text" value={text} onChange={onChange} />
            输出文本: {text}
        </div>
    );
}

function CharacterCount() {const count = useRecoilValue(charCountState);
    return <> 输出长度: {count}</>;
}
//charCounterStore.js
import {atom, selector} from 'recoil';

export const textState = atom({
    key: 'textState',
    default: ''
})
export const charCountState = selector({
    key: 'charCountState',
    get: ({get})=>{const text = get(textState)
        return text.length;
    }
})

写完这个 demo 给我的感觉就是,只有相熟 hook 语法,上手 Recoil 几乎 too EZ🐶,useRecoilState 很像 useState, 只不过 useRecoilState 接管的初始化参数是 atom or selector。当组件须要用到共享状态时(atom),只须要通过 Recoil hook 引入这个共享状态即可应用,当 atom 变动后,所有订阅这个 atom 的其余组件都会同步这个数据👍。


最初,提几点文中没提到的:

  • Recoil 能够将导航视为一等公民,甚至能够对链接中的状态进行编码。
  • Recoil 有与并发模式及其他 React 新个性兼容的可能性。
  • Recoil 能够应用 React 外部的调度机制,这是 Redux 和 Mobx 不反对的。
  • 劳动节高兴🥳🥳🥳

正文完
 0