大对象
下面的例子和描述都是基于这个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>);};