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

Next.js SSR页面刷新重复渲染服务端数据致内容不匹配问题求助

解决Next.js SSR中随机数组导致的Hydration不匹配问题

问题根源

你当前的代码在组件顶层直接执行随机数组生成逻辑,会引发以下问题:

  • 服务端SSR渲染时生成一次随机数组并输出对应HTML
  • 客户端Hydration阶段再次执行这段逻辑,生成另一个不同的随机数组
    两者内容不一致就触发了「Text content does not match server-rendered HTML」错误。

解决方案

方案一:在getServerSideProps中生成随机数组(推荐)

把随机数组的生成逻辑移到服务端的getServerSideProps里,传给组件的是已经生成好的固定随机数组,服务端和客户端拿到的完全一致,从根源避免内容不匹配。

修改后的代码:

const Quiz = ({ randomQuestionsArray }: { randomQuestionsArray: IQuestion[] }) => {
  let currentQuestion = 0;

  return (
    <div>{randomQuestionsArray[currentQuestion]}</div>
  )
}

export async function getServerSideProps() {
  const { data: questions } = await supabase.from('questions').select();
  const numberOfQuestions = 5;
  const randomQuestionsArray: IQuestion[] = [];

  // 生成不重复的随机题目
  const usedIndices = new Set();
  while (randomQuestionsArray.length < numberOfQuestions) {
    const randomIndex = Math.floor(Math.random() * questions.length);
    if (!usedIndices.has(randomIndex)) {
      usedIndices.add(randomIndex);
      randomQuestionsArray.push(questions[randomIndex]);
    }
  }

  return {
    props: {
      randomQuestionsArray,
    },
  }
}

方案二:在客户端用useEffect生成(适合不需要SSR展示随机内容的场景)

如果不需要服务端渲染出随机题目内容,可以把生成逻辑放到useEffect里,确保只在客户端首次渲染后执行一次:

import { useState, useEffect } from 'react';

const Quiz = ({ questions }: { questions: IQuestion[] }) => {
  const [currentQuestion, setCurrentQuestion] = useState(0);
  const [randomQuestionsArray, setRandomQuestionsArray] = useState<IQuestion[]>([]);
  const numberOfQuestions = 5;

  useEffect(() => {
    const generateRandomQuestionsArray = () => {
      const arr: IQuestion[] = [];
      const usedIndices = new Set();
      while (arr.length < numberOfQuestions) {
        const randomIndex = Math.floor(Math.random() * questions.length);
        if (!usedIndices.has(randomIndex)) {
          usedIndices.add(randomIndex);
          arr.push(questions[randomIndex]);
        }
      }
      return arr;
    };

    setRandomQuestionsArray(generateRandomQuestionsArray());
  }, [questions, numberOfQuestions]);

  // 渲染前判断数组是否生成完成,避免服务端渲染空内容导致的不匹配
  if (randomQuestionsArray.length === 0) {
    return <div>Loading...</div>;
  }

  return (
    <div>{randomQuestionsArray[currentQuestion]}</div>
  )
}

export async function getServerSideProps() {
  const { data } = await supabase.from('questions').select();

  return {
    props: {
      questions: data,
    },
  }
}

额外提示

原代码里的randomNumber变量未定义,需补充随机索引生成逻辑(比如Math.floor(Math.random() * questions.length)),同时建议加上去重逻辑,避免重复选中同一道题目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:55:14