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,问题仍未解决。
排查与解决方案
路由参数
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> ); };检查
Event组件内部的客户端依赖
排查Event组件是否直接使用了window、document等仅客户端可用的API,或依赖客户端状态渲染。这类代码需要放在useEffect中,或通过typeof window !== 'undefined'判断后执行,确保服务端渲染的DOM与客户端一致。静态路径参数格式问题
Next.js要求getStaticPaths返回的params.id必须是字符串,若后端返回的event.id是数字,需转换为字符串:paths: events.map((event) => ({ params: { id: String(event.id), }, }))本地依赖版本一致性
删除本地node_modules和package-lock.json,重新执行npm install,确保依赖版本与队友完全一致。
内容的提问来源于stack exchange,提问作者Arjun
相关产品推荐
相关产品推荐

