React SSR + Redux 导致的 Hydration 报错踩坑记录与修复方案

一条“Hydration failed”的错误,让我损失了半天时间

背景

我在用 Next.js App Router + Redux 开发一个任务管理应用,一切顺利,直到打开了 SSR(服务端渲染),突然看到这个令人头皮发麻的报错:

Hydration failed because the server rendered HTML didn't match the client.

报错定位在

,但实际问题比看上去复杂得多。


问题原因

React SSR 会先在服务端输出 HTML,再在浏览器执行 hydration,如果服务端和客户端渲染的 DOM 结构不一致,就会报错。

Redux 的状态通常在客户端初始化,比如 auth.isAuthenticated,在 SSR 阶段它通常是 false,但客户端可能已经是 true

举个例子:

{isAuthenticated ? (
  欢迎,{user?.username}
) : (
  登录
)}

服务端输出:

登录

客户端切换成:

欢迎,Luke

标签类型完全不一样,React hydration 直接炸了。


修复方式:引入 useIsClient
import { useEffect, useState } from 'react';

export function useIsClient() {
  const [isClient, setIsClient] = useState(false);
  useEffect(() => setIsClient(true), []);
  return isClient;
}

然后在你的组件中:

const isClient = useIsClient();

if (!isClient) return null; // 跳过 SSR 阶段

return isAuthenticated ? (
  欢迎,{user?.username}
) : (
  登录
);

这样 React SSR 阶段就不会渲染出错误结构,hydration 就能成功。


更进一步:封装 ClientOnly 组件
function ClientOnly({ children }: { children: React.ReactNode }) {
  const isClient = useIsClient();
  if (!isClient) return null;
  return <>{children};
}

任何你想跳过 SSR 的组件,只需要这样写:


  

结语

React SSR + Redux 状态管理配合 App Router 使用,确实不够“傻瓜式”。但一旦你掌握了客户端条件渲染与状态保护的技巧,这种问题就能快速应对。

你可能感兴趣的:(react.js,javascript,前端)