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}번</>}