Atoms in atom
atom()
创建一个原子配置,这是一个对象,但它不持有值。
原子配置没有字符串键,我们通过引用相等性来识别它们。
换句话说,我们可以像使用键一样使用原子配置。
在 useState 中存储原子配置
首先,我们可以在 useState 中存储原子配置。
const Component = ({ atom1, atom2 }) => {const [selectedAtom, setSelectedAtom] = useState(atom1)const [value] = useAtom(selectedAtom)return (<div>选中的值:{value}<button onClick={() => setSelectedAtom(atom1)}>选择一个原子</button><button onClick={() => setSelectedAtom(atom2)}>选择另一个原子</button></div>)}
注意,我们可以将原子配置作为 props 传递。
这可能没有任何意义,但我们可以按需创建一个原子配置。
const Component = () => {const [currentAtom, setCurrentAtom] = useState(() => atom(0))const [count, setCount] = useAtom(currentAtom)return (<div>计数:{count} <button onClick={() => setCount((c) => c + 1)}>+1</button><button onClick={() => setCurrentAtom(atom(0))}>创建新的</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}<button onClick={() => setNameAtom(firstNameAtom)}>显示名字</button><button onClick={() => setNameAtom(lastNameAtom)}>显示姓氏</button></div>)}
可以创建一个派生原子。
const derivedNameAtom = atom((get) => {const nameAtom = get(showingNameAtom)return get(nameAtom)})// 或者一个更短的版本const derivedNameAtom = atom((get) => get(get(showingNameAtom)))
为了避免混淆原子中的内容,明确命名原子是很重要的。 此外,TypeScript 类型信 息也会很有帮助。
在原子中存储原子配置的数组
最后,原子中的原子模式是将原子配置的数组存储到一个原子中。
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}>添加</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>)}