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

构建Next JS项目时出现‘navigator is not defined’错误

Next.js自定义Hook构建时触发"navigator is not defined"错误

我在Next.js中实现了一个自定义Hook,通过navigator.onLine属性获取网络在线状态,本地开发环境运行完全正常,但执行npm run build命令构建项目时,抛出了‘navigator is not defined’的错误。我清楚这个问题和水合渲染、预渲染机制有关,但尝试了各种已知方案都没能修复,目前有7个使用该Hook的文件都出现了这个错误。

以下是我的自定义Hook代码:

"use client";
import { useEffect, useState } from "react";

const useNetworkStatus = () => {
  const [isOnline, setOnline] = useState<boolean>(true);

  const updateNetworkStatus = () => {
    if (typeof navigator !== 'undefined') {
      setOnline(navigator.onLine);
    }
  };

  // 部分浏览器load事件不触发,所以挂载时手动调用一次更新
  useEffect(() => {
    updateNetworkStatus();
  }, []);

  useEffect(() => {
    window.addEventListener("load", updateNetworkStatus);
    window.addEventListener("online", updateNetworkStatus);
    window.addEventListener("offline", updateNetworkStatus);

    return () => {
      window.removeEventListener("load", updateNetworkStatus);
      window.removeEventListener("online", updateNetworkStatus);
      window.removeEventListener("offline", updateNetworkStatus);
    };
  }, [navigator.onLine]);

  return { isOnline };
};

export default useNetworkStatus;

问题根源

错误的核心原因是第二个useEffect的依赖项navigator.onLine——在Next.js预渲染过程中,代码会在服务器端执行,此时浏览器的navigator对象不存在,直接访问navigator.onLine会触发"navigator is not defined"错误。

修复方案

修改两个关键地方:

  • 将初始状态改为函数式初始化,避免服务器端直接访问navigator
  • 移除第二个useEffect的navigator.onLine依赖项,改用事件监听捕获网络状态变化

修改后的完整代码:

"use client";
import { useEffect, useState } from "react";

const useNetworkStatus = () => {
  // 函数式初始化,仅在客户端执行时访问navigator
  const [isOnline, setOnline] = useState<boolean>(() => 
    typeof navigator !== 'undefined' ? navigator.onLine : true
  );

  const updateNetworkStatus = () => {
    if (typeof navigator !== 'undefined') {
      setOnline(navigator.onLine);
    }
  };

  // 初始挂载时更新状态
  useEffect(() => {
    updateNetworkStatus();
  }, []);

  useEffect(() => {
    window.addEventListener("load", updateNetworkStatus);
    window.addEventListener("online", updateNetworkStatus);
    window.addEventListener("offline", updateNetworkStatus);

    return () => {
      window.removeEventListener("load", updateNetworkStatus);
      window.removeEventListener("online", updateNetworkStatus);
      window.removeEventListener("offline", updateNetworkStatus);
    };
  }, []); // 移除navigator.onLine依赖,事件监听已能捕获状态变化

  return { isOnline };
};

export default useNetworkStatus;

修复说明

  1. 函数式初始状态:useState的函数式初始化参数只会在组件首次渲染时执行一次,而且在服务器端渲染时,这个函数会判断navigator是否存在,避免直接访问不存在的对象。
  2. 移除依赖项:网络状态的变化已经通过online/offline事件监听来捕获,不需要把navigator.onLine作为useEffect的依赖项,这样就能避免服务器端执行时访问navigator引发的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:44:58