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

为何在useState中使用Math.random()会引发服务端渲染问题?

问题原因

直接在useState的初始值里用Math.random()会触发Hydration失败,核心原因是服务端渲染(SSR)和客户端首次生成的随机值不一致。

SSR过程中,服务器会执行组件代码生成初始UI,此时Math.random()会生成一个随机结果;当客户端加载页面进行Hydration时,会再次执行这段代码生成新的随机值——两次结果大概率不同,导致服务器输出的UI和客户端初始渲染的UI不匹配,触发报错。

而直接传固定的true或false时,服务端和客户端的初始状态完全一致,自然不会有这个问题。

解决方案

方案1:用useEffect在客户端挂载后设置状态

把随机逻辑放到useEffect中,这段代码只会在客户端组件挂载后执行,避免服务端和客户端的结果冲突:

import { useState, useEffect } from 'react';

function YourComponent() {
  const [hasPrime, setHasPrime] = useState(false); // 服务端和客户端共用同一个初始值

  useEffect(() => {
    // 仅在客户端执行随机判断
    setHasPrime(Math.random() < 0.5);
  }, []);

  return (
    <>
      {hasPrime && (
        <div>
          <p>Free Next-day delivery</p>
        </div>
      )}
    </>
  );
}

方案2:用useLayoutEffect同步更新UI(可选)

如果需要在DOM更新前就完成状态设置,避免UI闪烁,可替换成useLayoutEffect,逻辑和上面一致:

import { useState, useLayoutEffect } from 'react';

function YourComponent() {
  const [hasPrime, setHasPrime] = useState(false);

  useLayoutEffect(() => {
    setHasPrime(Math.random() < 0.5);
  }, []);

  // 渲染逻辑和方案1一致
}

方案3:客户端环境判断(快速适配)

通过typeof window !== 'undefined'判断是否在客户端,确保服务端用固定初始值,客户端再生成随机值:

const [hasPrime] = useState(typeof window !== 'undefined' ? Math.random() < 0.5 : false);

注意:这种方式下服务端渲染的UI不会显示该元素,客户端挂载后会突然出现,可能有闪烁,适合对UI连贯性要求不高的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:45:35