v2 API migration
RFC: https://github.com/pmndrs/jotai/discussions/1514
Jotai v1은 2022년 6월에 출시되었으며, 다양한 피드백을 받았습니다. React도 Promise에 대한 퍼스트클래스 지원을 제안하고 있습니다. Jotai v2에는 새로운 API가 추가될 예정입니다.
안타깝게도, 새로운 기능과 함께 몇 가지 호환성이 깨지는 변경 사항이 있습니다.
What are new features
바닐라 라이브러리
Jotai는 바닐라(React를 사용하지 않는) 함수와 React 함수를 별도로 제공합니다. 이들은 jotai/vanilla
와 같은 별도의 진입점에서 제공됩니다.
Store API
Jotai는 스토어 인터페이스를 제공하여 여러분이 직접 atom 값을 조작할 수 있게 합니다.
import { createStore } from 'jotai' // 또는 'jotai/vanilla'에서 가져올 수 있습니다.const store = createStore()store.set(fooAtom, 'foo')console.log(store.get(fooAtom)) // "foo"를 출력합 니다.const unsub = store.sub(fooAtom, () => {console.log('스토어 내 fooAtom 값이 변경되었습니다.')})// unsub()를 호출하여 구독을 해제할 수 있습니다.
또한, 여러분만의 React Context를 생성하여 스토어를 전달할 수도 있습니다.
더 유연한 아톰 write
함수
write
함수는 여러 개의 인자를 받을 수 있고, 값을 반환할 수도 있습니다.
atom((get) => get(...),(get, set, arg1, arg2, ...) => {...return someValue})
What are breaking
비동기 아톰은 더 이상 특별하지 않습니다
비동기 아톰은 단순히 Promise 값을 가진 일반 아톰입니다.
아톰의 getter 함수는 Promise를 해결하지 않습니다.
반면에 useAtom
훅은 계속해서 Promise를 해결합니다.
splitAtom
과 같은 일부 유틸리티는 동기 아톰을 기대하며,
비동기 아톰에서는 작동하지 않습니다.
Writable atom 타입 변경 (TypeScript 전용)
// 이전WritableAtom<Value, Arg, Result extends void | Promise<void>>// 변경 후WritableAtom<Value, Args extends unknown[], Result>
일반적으로 WritableAtom
타입을 직접 사용하는 것은 피하는 것이 좋습니다.
일부 기능이 제거됨
- Provider의
initialValues
prop이 제거되었습니다.store
가 더 유연하기 때문입니다. - Provider의 scope props가 제거되었습니다. 여러분이 직접 컨텍스트를 생성할 수 있기 때문입니다.
abortableAtom
유틸리티가 제거되었습니다. 해당 기능이 기본적으로 포함되었기 때문입니다.waitForAll
유틸리티가 제거되었습니다.Promise.all
로 충분히 동작하기 때문입니다.
Migration guides
비동기 아톰
비동기 아톰의 get
함수는 프로미스를 자동으로 해결하지 않습니다. 따라서 await
나 .then()
을 사용해야 합니다.
간단히 말해, 변경 사항은 다음과 같습니다.
(타입스크립트 사용자라면 타입이 어디를 변경해야 하는지 알려줄 것입니다.)
이전 API
const asyncAtom = atom(async () => 'hello')const derivedAtom = atom((get) => get(asyncAtom).toUppercase())
새로운 API
const asyncAtom = atom(async () => 'hello')const derivedAtom = atom(async (get) => (await get(asyncAtom)).toUppercase())// 또는const derivedAtom = atom((get) => get(asyncAtom).then((x) => x.toUppercase()))
Provider's initialValues
prop
Previous API_nFpo6E2VMy6fLJpU4Lxsqk
const countAtom = atom(0)// 컴포넌트 내부<Provider initialValues={[[countAtom, 1]]}>...
const countAtom = atom(0)const HydrateAtoms = ({ initialValues, children }) => {useHydrateAtoms(initialValues)return children}// 컴포넌트 내부<Provider><HydrateAtoms initialValues={[[countAtom, 1]]}>...
Provider's scope
prop
const myScope = Symbol()// 부모 컴포넌트<Provider scope={myScope}>...</Provider>// 자식 컴포넌트useAtom(..., myScope)
const MyContext = createContext()const store = createStore()// 부모 컴포넌트<MyContext.Provider value={store}>...</MyContext.Provider>// 자식 컴포넌트const store = useContext(MyContext)useAtom(..., { store })
abortableAtom
유틸리티
이제 일반 atom
에서 지원되기 때문에, 더 이상 이전의 abortableAtom
유틸리티가 필요하지 않습니다.
Previous API_K7oqQc9QLUx8NhEdMYuHaG
const asyncAtom = abortableAtom(async (get, { signal }) => {...}
New API_iLthHtGNnNmpbKuw9s58a8
const asyncAtom = atom(async (get, { signal }) => {...}
waitForAll
유틸리티
이제 더 이상 이전의 waitForAll
유틸리티가 필요하지 않습니다.
네이티브 Promise API를 사용할 수 있기 때문입니다.
Previous API_haTiJuqET3bCzvaaR33qws
const allAtom = waitForAll([fooAtom, barAtom])
New API_Ys4YeF6YELZqn3rsfEfMJS
const allAtom = atom((get) => Promise.all([get(fooAtom), get(barAtom)]))
렌더링 함수 내에서 아톰을 생성하면 무한 루프가 발생할 수 있으니 주의하세요.
splitAtom
유틸리티 (또는 다른 유틸리티)와 비동기 아톰
splitAtom
유틸리티는 동기 아톰만 받을 수 있습니다.
비동기 아톰을 전달하기 전에 먼저 동기 아톰으로 변환해야 합니다.
이 규칙은 jotai-tanstack-query
의 atomsWithQuery
와 같은 다른 유틸리티에도 적용됩니다.
Previous API_Ei5CDD8JTheDBuj9pCiQWm
const splittedAtom = splitAtom(asyncArrayAtom)
New API_i9GyS5EDVp4P7oBsgdk3LZ
const splittedAtom = splitAtom(unwrap(asyncArrayAtom, () => []))
현재 unwrap
은 불안정하며 문서화되지 않았습니다.
대신 loadable
을 사용하면 로딩 상태를 더 잘 제어할 수 있습니다.
<Suspense>
를 사용해야 한다면, atoms-in-atom 패턴이 도움이 될 수 있습니다.
자세한 내용은 다음 토론을 참고하세요:
- https://github.com/pmndrs/jotai/discussions/1615
- https://github.com/jotaijs/jotai-tanstack-query/issues/21
- https://github.com/pmndrs/jotai/discussions/1751
Some other changes
유틸리티
atomWithStorage
유틸리티의delayInit
옵션이 기본값으로 제거되었습니다. 또한 첫 렌더링 시에는 항상initialValue
를 렌더링하고, 이후 렌더링에서는 저장된 값이 있다면 그 값을 렌더링합니다. 이 새로운 동작은 v1과 다릅니다. 자세한 내용은 https://github.com/pmndrs/jotai/discussions/1737을 참고하세요.useHydrateAtoms
는 이제 쓰기 가능한(writable) 아톰만 받을 수 있습니다.
Import 문
v2 API는 라이브러리 개발자와 React를 사용하지 않는 사용자를 위해 대체 진입점에서도 제공됩니다.
jotai/vanilla
jotai/vanilla/utils
jotai/react
jotai/react/utils
// v1.11.0부터 사용 가능import { atom } from 'jotai/vanilla'import { useAtom } from 'jotai/react'// v2.0.0부터 사용 가능import { atom } from 'jotai' // 'jotai/vanilla'와 동일import { useAtom } from 'jotai' // 'jotai/react'와 동일
참고: ESM을 사용하지 않는다면, 트리 쉐이킹을 더 잘 활용하기 위해 jotai
대신 jotai/vanilla
등을 사용하는 것이 좋습니다.