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

Next.js动态更新服务端渲染Props时内容不匹配问题排查

问题分析与解决方案

核心错误点

  1. 组件Props接收方式错误:CommentList组件没有正确解构props对象,导致initialComments和postId参数值混乱,直接引发useQuery配置错误,数据不匹配。
  2. 未同步React Query的SSR缓存:服务端渲染的评论数据未传递给客户端,客户端hydrate时重新请求数据,若此时数据已更新(比如新增评论已写入数据库),就会出现服务端与客户端渲染内容不一致的hydration错误。
  3. useState+useEffect修复方案错误:useEffect在hydration阶段不执行,初始状态为空数组,导致客户端初始渲染无评论,和服务端渲染内容矛盾,既解决不了问题还导致评论不显示。

分步解决方案

1. 修复组件Props接收方式

确保CommentList正确解构props,并给getComments传入postId参数:

const CommentList = ({ initialComments, postId }) => {
  const { data: comments } = useQuery(
    ["comments", postId],
    async () => getComments(postId),
    { initialData: initialComments }
  );

  return (
    <>
      Comments: {comments.length}
      {/* 新增评论表单 */}
      {/* 评论列表 */}
    </>
  );
};

2. 配置React Query的SSR缓存同步

在_app.tsx中添加Hydrate组件,用于客户端hydration时读取服务端的缓存:

import { QueryClient, QueryClientProvider, Hydrate } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import type { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  const [queryClient] = React.useState(() => new QueryClient());

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={pageProps.dehydratedState}>
        <Component {...pageProps} />
      </Hydrate>
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  );
}

export default MyApp;

修改getServerSideProps,创建QueryClient并预获取评论数据,将缓存脱水后传递给页面:

import { QueryClient, dehydrate } from 'react-query';

export const getServerSideProps = async () => {
  const queryClient = new QueryClient();
  const post = await getPost();

  // 预获取该文章的评论,存入QueryClient缓存
  await queryClient.prefetchQuery(
    ["comments", post.id],
    () => getComments(post.id)
  );

  return {
    props: {
      post,
      dehydratedState: dehydrate(queryClient),
    },
  };
};

此时CommentList可去掉initialData,直接从缓存读取数据:

const CommentList = ({ postId }) => {
  const { data: comments } = useQuery(["comments", postId], () => getComments(postId));

  return (
    <>
      Comments: {comments?.length || 0}
      {/* 新增评论表单 */}
      {/* 评论列表 */}
    </>
  );
};

3. 确保新增评论后的缓存更新正确

确认useCreateCommentMutation的postId参数传递正确,setQueryData的queryKey与useQuery一致:

export const useCreateCommentMutation = (postId: string) => {
  const queryClient = useQueryClient();

  return useMutation(
    async (values) => await axios.post("/api/comments", { ...values, postId }),
    {
      onSuccess: (res) => {
        queryClient.setQueryData<CommentWithAuthor[]>(
          ["comments", postId],
          (prev) => [...(prev || []), res.data]
        );
      },
    }
  );
};

这样处理后,服务端渲染内容与客户端hydration内容完全一致,不会再出现文本不匹配的错误,同时新增评论后能动态更新列表,SEO也能得到保证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:45:34