You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js + RTK Query:如何实现服务端渲染预取数据并支持数据更新?

解决RTK Query服务端预取静态HTML+客户端更新问题

核心思路

要实现服务端预取数据生成静态HTML,同时保留RTK Query的客户端更新能力,需要让服务端先获取数据并填充RTK Query缓存,再将缓存状态传递给客户端,客户端Hydrate时直接复用缓存,避免初始加载指示器。

代码修改步骤

1. 服务端页面预取数据并传递缓存状态

修改app/discussions/page.tsx,在服务端执行时预取数据,并用RTK Query的dehydrate序列化缓存,再通过Hydrate组件传递给客户端:

import { dehydrate, Hydrate } from '@reduxjs/toolkit/query/react';
// 导入你的RTK Query API实例(假设定义在services/discussionsApi.ts)
import { api } from '../services/discussionsApi';
import { DiscussionList } from '../components/DiscussionList';

export default async function DiscussionListPage() {
    // 服务端预取数据,填充RTK Query缓存
    await api.fetchDiscussions.initiate().unwrap();
    
    // 序列化缓存状态,用于客户端Hydrate
    const dehydratedState = dehydrate(api);

    return (
        <Hydrate state={dehydratedState}>
            <DiscussionList />
        </Hydrate>
    );
}

2. 调整客户端组件逻辑

修改app/components/DiscussionList.tsx,去掉初始加载指示器的判断(因为服务端已预取数据,客户端Hydrate时直接从缓存读取),同时保留RTK Query的更新能力:

import { useFetchDiscussionsQuery } from '../services/discussionsApi';

// 假设你的讨论数据类型定义
type Discussion = {
    discussionId: string;
    title: string;
    body: string;
};

export function DiscussionList() {
    const { data } = useFetchDiscussionsQuery();

    // 仅保留极端情况的兜底(正常服务端预取后不会触发)
    if (!data) {
        return <p>Loading...</p>;
    }

    return (
        <ul>
            {data.map((item: Discussion) => (
                <li key={item.discussionId}>
                    <h2>{item.title}</h2>
                    <p>{item.body}</p>
                </li>
            ))}
        </ul>
    );
}

3. 确保RTK Query API实例配置正确

你的RTK Query API实例(比如services/discussionsApi.ts)需要是单例,确保服务端和客户端使用同一实例:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const api = createApi({
    reducerPath: 'discussionsApi',
    baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
    endpoints: (builder) => ({
        fetchDiscussions: builder.query({
            query: () => '/discussions',
            // 可选:添加标签用于缓存更新
            providesTags: ['Discussion'],
        }),
        // 其他更新/删除端点可以用invalidatesTags来触发缓存刷新
    }),
});

export const { useFetchDiscussionsQuery } = api;

关键说明

  • 服务端预取:通过api.fetchDiscussions.initiate().unwrap()在服务端触发查询,填充RTK Query缓存
  • 缓存传递:dehydrate将缓存序列化为可传递的状态,Hydrate组件让客户端RTK Query读取该缓存,避免重复请求
  • 客户端更新:RTK Query仍会正常处理后续的数据更新(比如调用更新端点后,缓存会自动刷新,组件也会重新渲染)

内容的提问来源于stack exchange,提问作者Daniel Tonon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:59:56