Closed6
JotaiのProviderあり/なし、Store明示/非明示パターン

Jotaiを使っていて、
-
getDefaultStore()
を使ってるつもりなのに値が違う - Reactの外側からatomを読もうとして反映されてない
みたいなハマりがあったので、
「Providerあり/なし × Store明示/非明示」 の4パターンで挙動を整理してみる。
Providerなし | Providerあり | |
---|---|---|
Storeを明示する | ✅ よくある | ✅ ベストプラクティス |
Store非明示 | ✅ デフォルト | ⚠️ ハマりやすい |
それぞれで「React内からatomを読む」「React外から読む」を検証する。

✅ パターン1:Providerなし × Store明示
🧠 createStore()
で明示的にStoreを生成して使う。
React内から読む
import { useAtom } from 'jotai'
import { myAtom } from './atoms'
import { appStore } from './store'
function MyComponent() {
const [value] = useAtom(myAtom, { store: appStore })
return <div>{value}</div>
}
React外から読む
import { appStore } from './store'
import { myAtom } from './atoms'
const value = appStore.get(myAtom)
✅ 明示的なので安全。ライブラリ的なコードや複数ストアを扱う場合に◎。

✅ パターン2:Providerなし × Store非明示(getDefaultStore)
🧠 最も手軽な「デフォルトStore」使用パターン。
React内から読む
import { useAtom } from 'jotai'
import { myAtom } from './atoms'
function MyComponent() {
const [value] = useAtom(myAtom) // store指定なしでOK
return <div>{value}</div>
}
React外から読む
import { getDefaultStore } from 'jotai'
import { myAtom } from './atoms'
const store = getDefaultStore()
const value = store.get(myAtom)
✅ 小規模アプリや試作ならこれで十分。

✅ パターン3:Providerあり × Store明示(createStore)
🧠 createStore()で明示的に作ったStoreを、Providerで渡す王道パターン。
React内から読む
// main.tsx
import { Provider } from 'jotai'
import { appStore } from './store'
<Provider store={appStore}>
<MyComponent />
</Provider>
import { useAtom } from 'jotai'
import { myAtom } from './atoms'
function MyComponent() {
const [value] = useAtom(myAtom) // Provider内ならstore指定不要
return <div>{value}</div>
}
React外から読む
import { appStore } from './store'
import { myAtom } from './atoms'
const value = appStore.get(myAtom)
✅ テスト・本番・開発でStoreを切り替えたいならこの構成がベスト。

⚠️ パターン4:Providerあり × Store非明示
🧠 Providerは使ってるけど store を渡していないケース。
<Provider>
<App />
</Provider>
このときJotaiは内部で自動的に createStore()
している。
つまり、getDefaultStore()
で取得されるStoreとは別物。
React内から読む
import { useAtom } from 'jotai'
import { myAtom } from './atoms'
function MyComponent() {
const [value] = useAtom(myAtom) // Provider内では問題なく動く
return <div>{value}</div>
}
✅ React内では使える。
React外から読む
import { getDefaultStore } from 'jotai'
import { myAtom } from './atoms'
const value = getDefaultStore().get(myAtom) // ❌ ProviderのStoreとは別物
❌ 値が反映されてないように見える。

📝 まとめ
-
getDefaultStore() は Provider の Storeと別物になることがある
-
Reactの外側からatomを読む必要があるなら、storeは明示的に作る必要がある。
- createStore() → Provider store={...} → store.get(atom) の3点セット。
-
「なんかatomの値が反映されてない?」というとき、実はstoreが2つになってることを考える。
このスクラップは4ヶ月前にクローズされました