atomWithListeners
atomWithListeners
创建了一个原子和一个钩子。这个钩子可以被调用来 添加一个新的监听器。这个钩子接受一个回调函数作为参数,每次设置原子的值时, 都会调用这个回调函数。钩子还 返回一个函数来移除监听器。
这在你想创建一个组件来监听原子状态的变化时非常有用,而无需在每次状态变化时都重新渲染该组件。
import { useEffect } from 'react'import { atom, useSetAtom, Getter, Setter, SetStateAction } from 'jotai'type Callback<Value> = (get: Getter,set: Setter,newVal: Value,prevVal: Value,) => voidexport function atomWithListeners<Value>(initialValue: Value) {const baseAtom = atom(initialValue)const listenersAtom = atom<Callback<Value>[]>([])const anAtom = atom((get) => get(baseAtom),(get, set, arg: SetStateAction<Value>) => {const prevVal = get(baseAtom)set(baseAtom, arg)const newVal = get(baseAtom)get(listenersAtom).forEach((callback) => {callback(get, set, newVal, prevVal)})},)const useListener = (callback: Callback<Value>) => {const setListeners = useSetAtom(listenersAtom)useEffect(() => {setListeners((prev) => [...prev, callback])return () =>setListeners((prev) => {const index = prev.indexOf(callback)return [...prev.slice(0, index), ...prev.slice(index + 1)]})}, [setListeners, callback])}return [anAtom, useListener] as const}
在一个组件中:
const [countAtom, useCountListener] = atomWithListeners(0)function EvenCounter() {const [evenCount, setEvenCount] = useState(0)useCountListener(useCallback((get, set, newVal, prevVal) => {// 每次设置 `countAtom` 的值时,我们都会检查它的新值是否为偶数,// 如果是,我们就增加 `evenCount`。if (newVal % 2 === 0) {setEvenCount((c) => c + 1)}},[setEvenCount],),)return <>计数被设置为偶数 {evenCount} 次。</>}