概要
Next.js と Redux Toolkit を使ってみたくて検証していたところ、
A画面→B画面に遷移した際にA画面で保存したStoreの内容がB画面で
取得できないという事象に遭遇しました。
解決してみれば超単純な修正でしたが、そこに至るまで迷走したのでメモ残します。
技術要素
主な技術要素は以下の通りですが、今回の記事では技術要素の説明は割愛します。
ダメな例
まずはダメだったコードです。
- 補足
- Reducer の中身はここでは割愛
- configureStore は Redux Toolkit の Store を作るための便利関数
store.ts
const createStore = () => {
const middlewareList = [...getDefaultMiddleware(), logger];
return configureStore({
reducer: rootReducer,
middleware: middlewareList,
devTools: process.env.NODE_ENV !== 'production',
preloadedState: preloadedState(),
});
};
export default createStore;
_app.tsx
import { Provider } from 'react-redux'
// 省略
...
return (
<>
// 省略
...
<Provider store={createStore()}>
<Component {...pageProps} />
</Provider>
</>
);
原因はここでした。
<Provider store={createStore()}>
これは Next.js を使ってなければ動くっぽいですが、Next.js の場合は動きません。
ページ遷移する度にこのcreateStore
関数が呼び出され、Storeがクリアされてしまっていました。
(クリアというか正確には InitialState で初期化されます)
Redux Toolkit を使わず Redux だけを使用する場合も同様、関数呼び出しではダメです。
ちゃんと動いた例
ではどうするのか。
store.ts
const middlewareList = [...getDefaultMiddleware(), logger]
const store = configureStore({
reducer: rootReducer,
middleware: middlewareList,
devTools: process.env.NODE_ENV !== 'production',
preloadedState: preloadedState(),
})
export default store
_app.tsx
import { Provider } from 'react-redux'
// 省略
...
return (
<>
// 省略
...
<Provider store={store}> // <--- ここです
<Component {...pageProps} />
</Provider>
</>
);
はい。関数呼び出しをやめただけで動きました。
公式ページ でもこの書き方になっていますね。
まとめ
Next.js を使用する際は store の関数呼び出しはしないこと!
ただググると関数呼び出し例がヒットする時があるので、Next.js を使う際は気をつけましょう。