可监听变化的 atom
一个 atom 内容的变化通常只有使用useAtom
获取 atom 的值以后,才可能完成其中值变化的监听,而且功能也非常少。这里提供一个创建可被监听的 atom 的工具函数,其创建的 atom 可以被监听,可以使用回调函数在 atom 的set
方法被调用的时候处理响应 atom 值变化的逻辑。
type Callback<Value> = (
get: Getter,
set: Setter,
newVal: Value,
prevVal: Value
) => void;
export 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;
}
这个 atom 在创建的时候,除了会返回 atom 本身,还会返回一个 Hook。这个 Hook 可以接受一个类型为(get, set, newValue, prevValue) => void
的回调函数,并且在 atom 值发生变化的时候调用这个回调函数。为了回调函数的稳定引用,可以在组件中使用useCallback
来定义这个回调函数。