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

React SSR应用中className服务端与客户端不匹配问题求助

解决React SSR中localStorage导致className不匹配的警告问题

问题原因

服务端渲染(SSR)过程中无法访问浏览器的localStorage,你的初始状态useState(checkExpanded())在服务端会返回undefined,对应渲染className="hidden";但客户端初始渲染时能读取localStorage,checkExpanded()返回存储值或默认true,对应渲染className="inline",二者DOM结构不匹配,触发警告。

解决思路

让服务端和客户端初始渲染的状态完全一致,待客户端完成水合(hydrate)后,再从localStorage读取真实状态更新组件。这样既避免SSR不匹配,又能保留本地存储的状态记忆。

修改后的代码

// 服务端和客户端统一初始状态为false(对应className="hidden")
const [expanded, setExpanded] = useState(false);

const toggleExpanded = () => {
  setExpanded(!expanded);
};

// 客户端水合完成后,读取localStorage更新状态
useEffect(() => {
  const sidebarState = localStorage.getItem("sidebarState");
  // 有存储值则用存储值,无则用默认true
  setExpanded(sidebarState ? JSON.parse(sidebarState) : true);
}, []);

// 保存状态到localStorage
useEffect(() => {
  localStorage.setItem("sidebarState", JSON.stringify(expanded));
}, [expanded]);

// 渲染逻辑不变
<span className={expanded ? "inline" : "hidden"}>{item.text}</span>

关键说明

  1. 初始状态设为服务端能识别的固定值(比如false),确保服务端和客户端第一次渲染的DOM完全一致,消除警告。
  2. 利用useEffect的空依赖数组,确保只在客户端水合完成后执行一次状态更新,此时修改状态只会触发客户端的DOM更新,不会影响SSR结果。
  3. 移除了原有的checkExpanded函数,简化逻辑的同时避免服务端/客户端初始状态不一致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:52:21