原子中的 Atom
atom()
创建一个原子配置,它是一个对象,但它没有值。
Atom 配置没有字符串键,我们用引用相等性来标识它们。
换句话说,我们可以像 key 一样使用原子配置。
在 useState 中存储原子配置
首先,我们可以在 useState 中存储一个原子配置。
const Component = ({ atom1, atom2 }) => {const [selectedAtom, setSelectedAtom] = useState(atom1);const [value] = useAtom(selectedAtom);return (<div>Selected value: {value}<button onClick={() => setSelectedAtom(atom1)}>Select an atom</button><button onClick={() => setSelectedAtom(atom2)}>Select another atom</button></div>);};
请注意,我们可以将原子配置作为 props 传递。
它可能没有任何意义,但我们可以按需创建原子配置。
const Component = () => {const [currentAtom, setCurrentAtom] = useState(() => atom(0));const [count, setCount] = useAtom(currentAtom);return (<div>Count: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button><button onClick={() => setCurrentAtom(atom(0))}>Create new</button></div>);};
在原子中存储原子配置
同样,我们可以将一个原子配置存储为另一个原子的值。
const firstNameAtom = atom("Tanjiro");const lastNameAtom = atom("Kamado");const showingNameAtom = atom(firstNameAtom);const Component = () => {const [nameAtom, setNameAtom] = useAtom(showingNameAtom);const [name] = useAtom(nameAtom);return (<div>Name: {name}<button onClick={() => setNameAtom(firstNameAtom)}>Show First Name</button><button onClick={() => setNameAtom(lastNameAtom)}>Show Last Name</button></div>);};
可以创建派生原子。
const derivedNameAtom = atom((get) => {const nameAtom = get(showingNameAtom);return get(nameAtom);});// 或者更短的版本const derivedNameAtom = atom((get) => get(get(showingNameAtom)));
为了避免混淆原子中的内容,明确命名原子很重要。 此外,TypeScript 类型信息也会有所帮助。
在原子中存储原子配置数组
最后,atom pattern 中的 atom 是将一个 atom config 数组存储到一个 atom 中。
const countsAtom = atom([atom(1), atom(2), atom(3)]);const Counter = ({ countAtom }) => {const [count, setCount] = useAtom(countAtom);return (<div>{count} <button onClick={() => setCount((c) => c + 1)}>+1</button></div>);};const Parent = () => {const [counts, setCounts] = useAtom(countsAtom);const addNewCount = () => {const newAtom = atom(0);setCounts((prev) => [...prev, newAtom]);};return (<div>{counts.map((countAtom) => (<Counter countAtom={countAtom} key={countAtom} />))}<button onClick={addNewCount}>Add</button></div>);};
这种方法的好处是,如果你增加一个计数, 只有相应的 Counter 组件重新渲染,没有其他组件重新渲染。
重要的是要注意 anAtom.toString()
返回一个唯一的 id,它可以用作 map 中的 key
。
给 TypeScript 用户的提示
<Counter countAtom={countAtom} key={`${countAtom}`} />
在原子中存储原子配置映射
同样,我们可以存储对象映射而不是数组。
const pricesAtom = atom({apple: atom(15),orange: atom(12),pineapple: atom(25),});const Fruit = ({ name, priceAtom }) => {const [price] = useAtom(priceAtom);return (<div>{name}: {price}</div>);};const Parent = () => {const [prices] = useAtom(pricesAtom);return (<div>{Object.keys(prices).map((name) => (<Fruit name={name} priceAtom={prices[name]} key={name} />))}</div>);};