サーバーサイドレンダリング
Next.jsでのサーバーサイドレンダリング
RTK Queryは、Next.jsを使用したサーバーサイドレンダリング(SSR)を、リハイドレーションとnext-redux-wrapperの組み合わせでサポートしています。
ワークフローは以下の通りです
next-redux-wrapperを設定しますgetStaticPropsまたはgetServerSideProps内でinitiateアクションを使用して、すべてのクエリをプリフェッチします。例:store.dispatch(api.endpoints.getPokemonByName.initiate(name))await Promise.all(dispatch(api.util.getRunningQueriesThunk()))を使用して、各クエリが完了するのを待ちます
createApi呼び出しで、extractRehydrationInfoオプションを使用してリハイドレーションを設定します- TypeScript
- JavaScript
next-redux-wrapperリハイドレーションの例import type { Action, PayloadAction } from '@reduxjs/toolkit'
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { HYDRATE } from 'next-redux-wrapper'
type RootState = any // normally inferred from state
function isHydrateAction(action: Action): action is PayloadAction<RootState> {
return action.type === HYDRATE
}
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
extractRehydrationInfo(action, { reducerPath }): any {
if (isHydrateAction(action)) {
return action.payload[reducerPath]
}
},
endpoints: (build) => ({
// omitted
}),
})next-redux-wrapperリハイドレーションの例import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { HYDRATE } from 'next-redux-wrapper'
function isHydrateAction(action) {
return action.type === HYDRATE
}
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
extractRehydrationInfo(action, { reducerPath }) {
if (isHydrateAction(action)) {
return action.payload[reducerPath]
}
},
endpoints: (build) => ({
// omitted
}),
})
next.jsを使用した例のリポジトリはこちらで入手できます。
メモリリークは想定されていませんが、レンダリングがクライアントに送信され、ストアがメモリから削除される際に、store.dispatch(api.util.resetApiState())を呼び出して、不正なタイマーが実行されたままにならないようにすることもできます。
静的サイト生成(SSG)で古いデータを提供しないようにするには、refetchOnMountOrArgChangeを、ページが生成されてからそれほど時間が経過していない場合にデータが再フェッチされるように、900(秒)などの適切な値に設定するとよいでしょう。
他の場所でのサーバーサイドレンダリング
next.jsを使用しておらず、上記の例をSSRフレームワークに適合させることができない場合、エフェクト内で安全にではなく、レンダリング中に非同期コードを実行する必要があるSSRシナリオをサポートするために、unstable__マーク付きのアプローチが利用可能です。これは、getDataFromTreeをApolloで使用するのと同様のアプローチです。
ワークフローは以下の通りです
レンダリング中に非同期処理を実行する
createApiのバージョンを作成します- TypeScript
- JavaScript
import {
buildCreateApi,
coreModule,
reactHooksModule,
} from '@reduxjs/toolkit/query/react'
const createApi = buildCreateApi(
coreModule(),
reactHooksModule({ unstable__sideEffectsInRender: true })
)import {
buildCreateApi,
coreModule,
reactHooksModule,
} from '@reduxjs/toolkit/query/react'
const createApi = buildCreateApi(
coreModule(),
reactHooksModule({ unstable__sideEffectsInRender: true })
)const api = createApi({...})を呼び出すときに、カスタムのcreateApiを使用します次のレンダリングサイクルを実行する前に、
await Promise.all(dispatch(api.util.getRunningQueriesThunk()))を使用して、すべてのクエリが完了するのを待ちます