JotaiJotai

状態
原始和灵活的 React 状态管理

大对象

下面的例子和描述都是基于这个codesandbox,所以如果你能更好地理解它 将其与这些示例一起查看。

有时我们有需要存储在原子中的嵌套数据,我们可能需要在不同级别更改该数据,或者我们需要使用部分数据而不监听所有更改。

考虑这个例子:

const initialData = {
people: [
{
name: "Luke Skywalker",
information: { height: 172 },
siblings: ["John Skywalker", "Doe Skywalker"],
},
{
name: "C-3PO",
information: { height: 167 },
siblings: ["John Doe", "Doe John"],
},
],
films: [
{
title: "A New Hope",
planets: ["Tatooine", "Alderaan"],
},
{
title: "The Empire Strikes Back",
planets: ["Hoth"],
},
],
info: {
tags: ["People", "Films", "Planets", "Titles"],
},
};

focusAtom

focusAtom 根据您传递给它的 focus 创建一个新原子。 jotai-optics

我们使用此 utils 来 focus 原子并从数据的特定部分创建原子。 例如我们可能需要消费上述数据的 people 属性,我们是这样做的:

import { atom } from "jotai";
import { focusAtom } from "jotai-optics";
const dataAtom = atom(initialData);
const peopleAtom = focusAtom(dataAtom, (optic) => optic.prop("people"));

focusAtom 返回 WritableAtom,这意味着可以更改 peopleAtom 数据。

如果我们更改上述数据示例的 films 属性,则 peopleAtom 不会导致重新渲染,因此这是使用 focusAtom 的好处之一。

splitAtom

当您想为列表中的每个元素获取一个原子时,splitAtom 很有用。 jotai/utils

我们将此 utils 用于返回数组作为其值的原子。 例如,我们上面制作的 peopleAtom 返回 people 属性数组,因此我们可以为该数组的每个项目返回一个原子。 如果数组原子是可写的,则 splitAtom 返回的原子将是可写的,如果数组原子是只读的,则返回的原子也将是只读的。

import { splitAtom } from "jotai/utils";
const peopleAtomsAtom = splitAtom(peopleAtom);

这就是我们在组件中使用它的方式。

const People = () => {
const [peopleAtoms] = useAtom(peopleAtomsAtom);
return (
<div>
{peopleAtoms.map((personAtom) => (
<Person personAtom={personAtom} key={`${personAtom}`} />
))}
</div>
);
};

selectAtom

该函数创建一个派生原子,其值是原始原子值的函数。 jotai/utils

这个 utils 就像focusAtom,但是当我们有一个只读原子来选择它的一部分时我们使用它,它总是返回一个只读原子。

假设我们要消费 info 数据,它的数据是永远不变的。 我们可以从中创建一个只读原子并选择创建的原子。

// 首先我们基于 initialData.info 创建一个只读原子
const readOnlyInfoAtom = atom((get) => get(dataAtom).info);

然后我们在我们的组件中使用它:

import { atom, useAtom } from "jotai";
import { selectAtom, splitAtom } from "jotai/utils";
const tagsSelector = (s) => s.tags;
const Tags = () => {
const tagsAtom = selectAtom(readOnlyInfoAtom, tagsSelector);
const tagsAtomsAtom = splitAtom(tagsAtom);
const [tagAtoms] = useAtom(tagsAtomsAtom);
return (
<div>
{tagAtoms.map((tagAtom) => (
<Tag key={`${tagAtom}`} tagAtom={tagAtom} />
))}
</div>
);
};