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

Next.js SSR中document.querySelector失效问题的解决方法

解决Next.js中圆形进度条的"document is not defined"错误

错误原因

Next.js默认会在服务器端渲染页面,服务器环境里没有浏览器的document对象——你的圆形进度条组件大概率在初始化阶段直接访问了document,导致服务端渲染时抛出错误。


方法一:用Next.js Dynamic组件禁用SSR

这是最直接的解决方案,通过dynamic函数懒加载进度条组件,强制它只在客户端渲染,这样就能安全访问document了。

步骤如下:

  1. 导入dynamic函数:
import dynamic from 'next/dynamic';
  1. 动态导入你的进度条组件,同时禁用SSR:
// 替换成你实际的组件路径
const CircularProgressBar = dynamic(() => import('../components/CircularProgressBar'), {
  ssr: false,
  loading: () => <div>加载中...</div> // 可选,加载时的占位提示
});
  1. 在页面中正常使用这个组件:
import { useState } from 'react';

export default function Home() {
  const [progressEndValue, setProgressEndValue] = useState(50);

  return (
    <div>
      <CircularProgressBar endValue={progressEndValue} />
      <button onClick={() => setProgressEndValue(75)}>更新进度到75%</button>
    </div>
  );
}

方法二:在进度条组件内规避服务端访问document

如果不想用动态导入,可以在组件内部把访问document的逻辑限制在客户端执行,比如用useEffect(它只会在客户端触发),或者加类型判断:

示例组件代码:

import { useEffect, useRef } from 'react';

export default function CircularProgressBar({ endValue }) {
  const progressContainer = useRef(null);

  useEffect(() => {
    // 确保只在客户端执行,且容器存在
    if (!progressContainer.current || typeof document === 'undefined') return;

    // 这里写你的进度条渲染逻辑,比如操作DOM、初始化第三方库
    renderProgressBar(progressContainer.current, endValue);
  }, [endValue]); // 监听endValue变化,自动更新进度

  return <div ref={progressContainer}></div>;
}

function renderProgressBar(container, value) {
  // 这里可以安全使用document相关API
  const canvas = document.createElement('canvas');
  // ... 你的圆形进度条绘制代码
  container.appendChild(canvas);
}

注意事项

  • 如果你用了第三方进度条库(比如progressbar.js、Chart.js),一定要把初始化代码放在useEffect里,或者用库提供的SSR兼容方案。
  • 修改progressEndValue后,只要组件监听了这个值的变化(比如方法二中的useEffect依赖),进度条就会自动更新显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:20:30