メインコンテンツにスキップ

サーバーサイドレンダリング

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オプションを使用してリハイドレーションを設定します

    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.jsを使用した例のリポジトリはこちらで入手できます。

ヒント

メモリリークは想定されていませんが、レンダリングがクライアントに送信され、ストアがメモリから削除される際に、store.dispatch(api.util.resetApiState())を呼び出して、不正なタイマーが実行されたままにならないようにすることもできます。

ヒント

静的サイト生成(SSG)で古いデータを提供しないようにするには、refetchOnMountOrArgChangeを、ページが生成されてからそれほど時間が経過していない場合にデータが再フェッチされるように、900(秒)などの適切な値に設定するとよいでしょう。

他の場所でのサーバーサイドレンダリング

next.jsを使用しておらず、上記の例をSSRフレームワークに適合させることができない場合、エフェクト内で安全にではなく、レンダリング中に非同期コードを実行する必要があるSSRシナリオをサポートするために、unstable__マーク付きのアプローチが利用可能です。これは、getDataFromTreeApolloで使用するのと同様のアプローチです。

ワークフローは以下の通りです

  • レンダリング中に非同期処理を実行するcreateApiのバージョンを作成します

    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()))を使用して、すべてのクエリが完了するのを待ちます