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

Next.js构建后React Context返回null,开发模式正常

问题描述

我正在使用Next.js App Router开发应用,通过自定义useLoading钩子结合Context Provider管理全局加载状态。开发模式(npm run dev)下一切正常,但执行npm run build构建生产版本后,出现错误:Error: useLoading must be used within a LoadingProvider,此时useLoading中的Context返回null,尽管已在根布局中正确包裹LoadingProvider。

相关代码

src/context/LoadingContext.tsx

"use client";
import Loading from "@/pages/component/Loading";
import React, { createContext, FC, ReactNode, useState } from "react";

interface LoadingContextProps {
  setLoading: React.Dispatch<React.SetStateAction<boolean>>;
}

interface LoadingProviderProps {
  children: ReactNode;
}

const LoadingContext = createContext<LoadingContextProps | null>(null);

export const LoadingProvider: FC<LoadingProviderProps> = ({ children }) => {
  const [isLoading, setLoading] = useState<boolean>(false);

  return (
    <LoadingContext.Provider value={{ setLoading }}>
      <Loading isLoading={isLoading} />
      {children}
    </LoadingContext.Provider>
  );
};

export default LoadingContext;

src/hooks/useLoading.ts

import LoadingContext from "@/context/LoadingContext";
import { useContext } from "react";

export const useLoading = () => {
  const context = useContext(LoadingContext);
  if (!context) {
    // context returns null here
    throw new Error("useLoading must be used within a LoadingProvider", {
      cause: context,
    });
  }
  return context;
};

src/app/layout.tsx

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <LoadingProvider>
          <ThemeProvider defaultTheme="light">{children}</ThemeProvider>
        </LoadingProvider>
      </body>
    </html>
  );
}

使用方式

const {setLoading} = useLoading();
setLoading(false);
setLoading(true);

已尝试的操作

  • 确认LoadingProvider已正确包裹整个组件树
  • 验证问题仅出现在生产构建版本
  • 移除钩子相关实现后构建成功
解决方案

这个问题的核心原因是Next.js App Router的生产构建会对服务端组件(Server Component)做严格的静态分析:如果某个组件在服务端渲染阶段调用了useLoading钩子,而LoadingProvider是客户端组件(带有"use client"指令),服务端渲染时无法获取客户端Context,就会抛出这个错误。开发模式未做严格校验,所以不会触发问题。

具体修复步骤:

  1. 给所有调用useLoading的组件添加"use client"指令:Context和自定义钩子只能在客户端组件中使用,在这些组件的最顶部加上"use client",明确标记为客户端组件。
  2. 检查组件边界:确认ThemeProvider如果是客户端组件,也已正确添加"use client"指令,避免嵌套的客户端组件边界问题。
  3. 禁止在服务端组件中调用客户端钩子:生产构建的静态分析会严格拦截服务端组件中的客户端API调用,必须确保useLoading只在客户端组件内使用。
  4. 临时排查方案(不推荐用作最终修复):可以给Context设置一个空默认值,避免直接抛出错误,方便排查问题组件:
const LoadingContext = createContext<LoadingContextProps>({
  setLoading: () => {}
});

关键提醒

Next.js App Router中服务端组件与客户端组件的边界必须清晰:

  • 客户端组件(带"use client")可使用React状态、Context、自定义钩子等客户端API
  • 服务端组件禁止使用任何客户端专属API,生产构建会做严格校验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 19:25:14