react全局状态管理_Recoil - Facebook出品的全新React状态管理库

Recoil是Facebook推出的一种React状态管理库,旨在解决React组件状态共享和Context的局限性。它通过有向图模型实现状态流动,原子(Atoms)作为状态单位,选择器(Selectors)用于计算派生数据。Atoms和Selectors提供了类似React本地状态的接口,允许组件间无样板地共享状态,同时支持代码分割和高效的数据流。Recoil还兼容Concurrent模式,易于状态持久化。
摘要由CSDN通过智能技术生成

动机

出于兼容性和简单的原因,最好使用React内置的状态管理功能,而不是外部的全局状态。但是React有一定的局限性:

  • 组件的状态只能通过推送到共同祖先来共享,但这可能包括一个巨大的树,然后需要重新渲染。
  • Context只能存储一个单一的值,而不是一个不确定的值集,每个值都有自己的消费者。
  • 这两点使得我们很难将树的顶部(状态必须住的地方)与树的叶子(状态使用的地方)进行代码分割。

我们希望在保持API和语义和行为尽可能的接近React的同时,又能改进以上问题。

Recoil 定义了一个有向图,它与 React 树正交,但也是内在附着在 React 树上。状态变化从这个图的根部(我们称之为atom)通过纯函数(我们称之为selector)流向组件。原理如下:

  • 我们得到了一个无样板代码的API,其中共享状态具有和React本地状态一样简单的get/set接口(如果需要的话,还可以用Reducer等进行封装)。
  • 我们有可能与Concurrent模式和其他新的React功能兼容,让它们变得具有可用性。
  • 状态的定义是增量和分布式的,使得代码的拆分成为可能。
  • 状态可以用派生数据替换,而无需修改使用它的组件。
  • 派生数据可以在同步和异步之间移动,而无需修改使用它的组件。
  • 我们可以把导航作为一个一等概念来对待,甚至可以对链接中的状态转换进行编码。
  • 以一种向后兼容的方式持久化整个应用状态是很容易的,所以持久化的状态可以在应用的变更中保存下来。

概览

使用Recoil可以创建一个数据流的图,它从Atom(共享状态)通过Selector(纯函数)流到你的 React 组件。Atom是组件可以订阅的状态单位。Selector可以同步或异步转换这个状态。

Atoms

Atom是状态的单位。它们是可更新和可订阅的:当一个Atom被更新时,每个被订阅的组件都会用新的值来重新渲染。它们也可以在运行时创建。Atom可以用来代替 React 本地组件状态。如果从多个组件中使用同一个Atom,所有这些组件都会共享它们的状态。

Atom是使用atom函数创建的:

const fontSizeState = atom({
  key: 'fontSizeState',
  default: 14,
});

Atom需要一个唯一的key,这个key用于调试、持久化,以及某些高级的API,让你看到所有Atom的图。两个Atom有相同的key是一个错误,所以要确保它们是全局唯一的。和 React 组件状态一样,它们也有一个默认值。

要从组件中读取和写入Atom,我们使用一个名为useRecoilState的钩子。它就像React的useState一样,但现在组件之间可以共享状态:

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return (
    <button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
      Click to Enlarge
    </button>
  );
}

点击该按钮会把按钮的字体大小增加一个字号。但现在一些其他组件也可以使用同样的字体大小。

Selectors

Selectors是一个纯函数,它接受Atom或其他Selectors作为输入。当这些上游的Atom或Selectors被更新时,Selectors函数将被重新评估。组件可以像Atom一样订阅Selectors,当Selectors发生变化时,组件就会被重新渲染。

Selectors用于计算基于状态的派生数据。这让我们可以避免冗余状态,通常不需要reducers来保持状态的同步和有效。相反,一个最小的状态集被存储在Atom中,而其他的一切都作为该最小状态的函数有效计算。由于Selectors可以跟踪哪些组件需要它们,以及它们依赖哪些状态,因此它们使这种功能方法更加高效。

从组件的角度来看,Selectors和Atom具有相同的接口,因此可以相互替代。

Selectors是用selector函数来定义的:

const fontSizeLabelState = selector({
  key: 'fontSizeLabelState',
  get: ({get}) => {
    const fontSize = get(fontSizeState);
    const unit = 'px';

    return `${fontSize}${unit}`;
  },
});

get属性是要计算的函数。它可以使用传递给它的get参数访问Atom和其他Selectors的值。每当它访问另一个Atom或Selectors时,就会创建一个依赖关系,这样更新另一个Atom或Selectors就会导致这个Atom或Selectors被重新计算。

在这个fontSizeLabelState示例中,Selectors有一个依赖关系:fontSizeStateAtom。从概念上讲,fontSizeLabelStateSelectors的行为就像一个纯函数,它以fontSizeState作为输入,并返回一个格式化的字体大小标签作为输出。

Selectors可以使用useRecoilValue()来读取,它取一个Atom或Selectors作为参数并返回相应的值。我们不使用useRecoilState(),因为fontSizeLabelStateSelectors是不可写的(关于可写Selectors的更多信息,请参阅SelectorsAPI参考):

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  const fontSizeLabel = useRecoilValue(fontSizeLabelState);

  return (
    <>
      <div>Current font size: ${fontSizeLabel}</div>

      <button onClick={() => setFontSize(fontSize + 1)} style={{fontSize}}>
        Click to Enlarge
      </button>
    </>
  );
}

现在点击该按钮会触发两件事:它可以增加按钮的字体大小,同时还可以更新字体大小标签以反映当前的字体大小。

以上就是Recoil官方文档的部分简介。

想了解更多信息请查阅官方网站:https://recoiljs.org/

b88d008eabaa32ad9b37c96ccd05961f.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值