jotai 이것저것

1. jotai 에서 snapshot 상태를 참조해야한다면?

const handleAction = useAtomCallback(useCallback(async (get, set) => {
  // 필요한 값들을 액션 시작 시점에 저장
  const initialState = {
    user: get(userAtom),
    cart: get(cartAtom),
    // ...
  }

  await someAsyncOperation()

  // 저장해둔 초기 상태 사용
  console.log('Initial state was:', initialState)
}, []))

2. jotai 에서 어떤 인터페이스 써야하나

// 1. 단순 상태
const cartMapAtom = atom<Record<string, CartNode>>({})

// 2. 파생 상태 (recoil의 selector)
const cartCountAtom = atom((get) => 
  Object.keys(get(cartMapAtom)).length
)

// 3. 매개변수 필요 (캐싱 불필요) (recoil의 ~family)
const getCartAtom = (cartId: string) => atom(
  (get) => get(cartMapAtom)[cartId],
  (get, set, newValue) => set(cartMapAtom, {
    ...get(cartMapAtom),
    [cartId]: newValue
  })
)

// 4. 매개변수 필요 (캐싱 필요) ) (recoil의 ~family)
const cartAtomFamily = atomFamily((cartId: string) => atom(
  (get) => get(cartMapAtom)[cartId],
  (get, set, newValue) => set(cartMapAtom, {
    ...get(cartMapAtom),
    [cartId]: newValue
  })
))

atomFamily는 다음과 같은 경우사용하기.

즉, atomFamily는 atom 을 param 별로 캐싱하기 위한 일종의 팩토리.
대신, atomFamily 는 param 을 key 로 하는 캐시 맵을 생성하기 때문에, 적절히 캐시를 지워주지 않을 경우 메모리 누수가 발생할 수 있음.
따라서, param 이 자주 변경되는 경우에는 사용하면 좋지 않음.

3. jotai 의 캐싱 시스템

그리고 이 둘은 컴포넌트 생명주기와는 독립적임.

function useNetworkOnlyAtom<T>(atom: Atom<T>) {
  const [value] = useAtom(atom)
  const [, refresh] = useAtom(refreshAtom)

  useEffect(() => {
    refresh()
  }, []) 

  return [value, refresh] as const
}