Closed6

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

shichishichi

Jotaiを使っていて、

  • getDefaultStore() を使ってるつもりなのに値が違う
  • Reactの外側からatomを読もうとして反映されてない

みたいなハマりがあったので、
「Providerあり/なし × Store明示/非明示」 の4パターンで挙動を整理してみる。

Providerなし Providerあり
Storeを明示する ✅ よくある ✅ ベストプラクティス
Store非明示 ✅ デフォルト ⚠️ ハマりやすい

それぞれで「React内からatomを読む」「React外から読む」を検証する。

shichishichi

✅ パターン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)

✅ 明示的なので安全。ライブラリ的なコードや複数ストアを扱う場合に◎。

shichishichi

✅ パターン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)

✅ 小規模アプリや試作ならこれで十分。

shichishichi

✅ パターン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を切り替えたいならこの構成がベスト。

shichishichi

⚠️ パターン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とは別物

❌ 値が反映されてないように見える。

shichishichi

📝 まとめ

  • getDefaultStore() は Provider の Storeと別物になることがある

  • Reactの外側からatomを読む必要があるなら、storeは明示的に作る必要がある。

    • createStore() → Provider store={...} → store.get(atom) の3点セット。
  • 「なんかatomの値が反映されてない?」というとき、実はstoreが2つになってることを考える。

このスクラップは4ヶ月前にクローズされました