[note] jotai 筆記
- utils @ jot > api
TL;DR
import { atom, useAtom, useAtomValue } from 'jotai';
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
const isEditingAtom = atom(false);
const App = () => {
// normal usage
const [isEditing, setIsEditing] = useAtom(countAtom)
// if only need the setter
// useUpdateAtom can prevent unnecessary re-render
const setIsEditing = useUpdateAtom(isEditingAtom);
// if only need the getter
const isEditing = useAtomValue(isEditingAtom);
}
MISC
Resettable
resettable @ jotai > guides
使用 atomWithReset
和 useResetAtom
可以把取得一個 function 來把 atom 設回 default value:
const todoListAtom = atomWithReset([{ description: 'Add a todo', checked: false }])
const TodoList = () => {
const [todoList, setTodoList] = useAtom(todoListAtom)
const resetTodoList = useResetAtom(todoListAtom)
return <button onClick={resetTodoList}>Reset</button>;
}
Good Discussion
如果想要在 render 時不透過 useEffect 設定 atom 的初始值
Can an atom be initialized on the first render? @ Github Discussion
// https://github.com/pmndrs/jotai/discussions/581#discussioncomment-972361
const fooAtom = atom(null)
const ParentComponent = ({ foo }) => (
<Provider initialValues={[[fooAtom, foo]]}>
<ChildComponent />
</Provider>
)
const ChildComponent = () => {
const [foo, setFoo] = useAtom(fooAtom)
// foo is already initialized.
}
Provider and share atom
Jotai 本身也提供了類似 React Context 中 Provider 概念的 <Provider />
,所有在該 Provider 中使用到的 atom,都會隸屬在這個 Provider 底下(如果沒有用 Provider 的話,預設 atom 都是 global 的),atom 會往上找到最近一個的 <Provider />
。
如果有些 atom 想要在不同 Providers 間被共用的話,因為預設這個 atom 的狀態會被限縮在該 Provider 底下,導致無法被共用,這時候我們可以建立一個更高層的 Provider,並且搭配 scope
來達到。
舉例來說,如果希望在 Next.js 中建立能在 "Global Atom" 而不會被各自 modules 內的 <Provider />
給影響,可以這麼做(sample code):
在 _app.ts
加入 scope=global
的 Provider
// _app.ts
<Provider scope="global">
{/* ... */}
</Provider>
接著即使 Module 內有再使用 Provider,也可以透過 scope
找到 global 的 Provider 來取用資料(jotai 會往上找到最靠近且 scope 名稱一樣的 Provider):
const [isEditing, setIsEditing] = useAtom(isEditingAtom, 'global');