Provider 和 Store

仅仅使用atomuseAtom基本上就已经可以完成 Jotai 在一般项目中的使用了,但是在 Jotai 控制所有 atom 逻辑的背后,还有两个非常重要的基础设施存在,虽然这两个功能可能在项目中使用的几率偏小,但这并不等于它们就不重要。

Store

在 Jotai 的实际运行过程中,所有的 atom 并不是散在项目中的,它们都被存储在一个默认的 Store 中。这个默认的 Store 无需我们显式创建,它会由 Jotai 自动创建并放置进入组件树。

Store 中保存的都是各个 atom 的实例,所以比较有经验的读者看到这里,就应该可以想到,Store 是可以用来在组件树里创建和隔离 atom 实例的。事实上 Store 的常见用法也的确如此。

与 atom 一样,Store 也是一个需要定义在组件外部的内容。创建一个新的 Store 实例可以直接使用createStore函数,这个函数不需要参数,它的功能就是完成一个 Store 实例的创建。

一个 Store 所具备的基本功能是获取指定 atom 的值,更新指定 atom 的值和订阅 atom 的变化。这三个功能分别由 Store 实例的getsetsub三个方法提供。

Tip

这三个方法大部分情况下不需要我们手动去调用,下文介绍的Provider会代替我们完成Store的控制。不过在组件之外获取和更新atom的值还是要使用到Store提供的功能的,比如在React Router的loadaction方法中获取和更新atom的值。

对于 Jotai 提供的默认 Store,可以使用 Jotai 提供的函数getDefaultStore()来获取。这可以在不使用 Provider 的时候在项目中组件外部更新 atom 使用。

Provider

Provider 在上面一节中就已经提到了,它是 Jotai 提供的一个组件,它的主要功能就是向组件树中提供 atom 实例。Provider 在组件树中可以多次出现,嵌套使用还可以形成类似于 React 中Context的隔离上下文的功能。

如果在项目中不使用任何 Provider,那么这种模式在 Jotai 中被称为Provider-less模式,在这个模式下项目中所有的 atom 都将被保存在默认 Store 中,并且每一个 atom 有且仅有一个实例。

Provider 组件常用的属性是store,用来指定其下组件树中所访问的 atom 实例所保存的位置。一个 Provider 常见的使用形式是这样的:

const customStore = createStore();

const Root = () => {
  return (
    <Provider store={customStore}>
      <App />
    </Provider>
  );
};

在一个 Provider 下的组件树中要获取 Provider 提供的 Store,可以使用useStore Hook。

Tip

在Provider作用范围内使用useAtom等Hook来访问atom,所获取的atom实例是保存在组件树中距离最近的一个Provider提供的Store里的,这在组件外获取和更新atom的值的时候需要注意Store的选择和获取。