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

Next.js页面重载时出现Hydration错误问题求助

Next.js Hydration错误排查:event/[id]页面重载触发问题

问题描述

路由为event/[id]的活动详情页面,从url/eventList页面点击活动卡片进入时功能正常,但重载页面会触发Hydration错误,同组开发人员未遇到此问题。

环境版本

  • npm version: 8.19.3
  • node version: 16.17.0

报错信息

1. Text content does not match server-rendered HTML.
2. Error: Hydration failed because the initial UI does not match what was rendered on the server.
3. Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

/events/[id]页面代码

import Event from '../../../Components/Event/Event';
import { useRouter } from 'next/router';
import classes from './event.module.css';

const EventDetails = (props) => {
  const router = useRouter();

  const {
    query: { tid },
  } = router;

  return (
    <section style={{ minHeight: '91vh' }} className={classes.background}>
      <Event eventDetails={props.eventDetails} teamId={tid} />
    </section>
  );
};

export async function getStaticPaths() {
  const events = await fetch(
    process.env.NEXT_PUBLIC_BACKEND_API + 'events/'
  ).then((res) => res.json());

  return {
    fallback: false,
    paths: events.map((event) => {
      const eventId = event.id;
      return {
        params: {
          id: eventId,
        },
      };
    }),
  };
}

export async function getStaticProps(context) {
  const eventId = context.params.id;
  const res = await fetch(
    process.env.NEXT_PUBLIC_BACKEND_API + 'events/' + eventId
  );
  if (!res || res.status != 200) {
    return {
      notFound: true,
    };
  }
  const eventDetails = await res.json();
  return {
    props: {
      eventDetails: eventDetails,
    },
    revalidate: 100,
  };
}

export default EventDetails;

package.json配置

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "npm run prettify && next dev",
    "build": "npm run prettify && next build",
    "start": "next start",
    "lint": "npm run prettify && next lint",
    "prettify": "prettier --write \"**/*.{js, jsx}\""
  },
  "dependencies": {
    "@emotion/react": "11.10.4",
    "@emotion/server": "11.10.0",
    "@emotion/styled": "11.10.4",
    "@mui/icons-material": "5.10.6",
    "@mui/material": "5.10.6",
    "@mui/x-date-pickers": "^5.0.3",
    "cryptr": "^6.0.3",
    "dayjs": "^1.11.5",
    "intl": "^1.2.5",
    "mui-file-dropzone": "^4.0.2",
    "next": "12.2.5",
    "next-auth": "^4.12.0",
    "normalize.css": "^8.0.1",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-share": "^4.4.1",
    "react-toastify": "^9.0.8",
    "swr": "^1.3.0",
    "universal-cookie": "^4.0.4"
  },
  "devDependencies": {
    "eslint": "8.23.1",
    "eslint-config-next": "12.3.1",
    "eslint-config-prettier": "8.5.0",
    "prettier": "2.7.1"
  }
}

已尝试操作

修改getStaticPaths和getStaticProps,问题仍未解决。


排查与解决方案

  1. 路由参数tid导致服务端/客户端渲染不匹配
    服务端静态生成时,useRouter()无法获取URL查询参数tid,此时teamId为undefined;但客户端跳转时能正常拿到tid,导致Event组件渲染的UI在服务端和客户端不一致。
    修正方案:延迟获取tid并处理服务端渲染时的空状态

    const EventDetails = (props) => {
      const router = useRouter();
      const [teamId, setTeamId] = useState();
    
      useEffect(() => {
        if (router.query.tid) {
          setTeamId(router.query.tid);
        }
      }, [router.query]);
    
      // 服务端渲染或未获取到tid时,返回空或加载组件,避免不匹配
      if (typeof window === 'undefined' || !teamId) {
        return null;
      }
    
      return (
        <section style={{ minHeight: '91vh' }} className={classes.background}>
          <Event eventDetails={props.eventDetails} teamId={teamId} />
        </section>
      );
    };
    
  2. 检查Event组件内部的客户端依赖
    排查Event组件是否直接使用了window、document等仅客户端可用的API,或依赖客户端状态渲染。这类代码需要放在useEffect中,或通过typeof window !== 'undefined'判断后执行,确保服务端渲染的DOM与客户端一致。

  3. 静态路径参数格式问题
    Next.js要求getStaticPaths返回的params.id必须是字符串,若后端返回的event.id是数字,需转换为字符串:

    paths: events.map((event) => ({
      params: {
        id: String(event.id),
      },
    }))
    
  4. 本地依赖版本一致性
    删除本地node_modules和package-lock.json,重新执行npm install,确保依赖版本与队友完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:10:24