0

I’m building a Next.js app (App router), and I’m using a custom useLoading hook to manage a loading state across the application with a context provider. Everything works perfectly in development mode (npm run dev), but when I build the app (npm run build) and run it in production, I get the following error:

Error: useLoading must be used within a LoadingProvider

It seems that the context is null after the build, even though it's wrapped properly with LoadingProvider in the root layout.

Here’s my code:

// 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>
  );
}

usage:

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

Has anyone faced this issue before, or does anyone know what might be causing this behavior after the build?

Problems

  • In development mode (npm run dev), everything works fine. The useLoading hook returns the context as expected.

  • In building mode (npm run build), the context in useLoading becomes undefined, even though I’ve wrapped the component tree with LoadingProvider in the root layout.

    I’m not sure why the context is working correctly in development but returns null on the process of building the app.

Things I've tried

  • Double-checked that LoadingProvider is correctly wrapping the entire component tree.
  • Verified that the issue only appears in the production build.
  • Tried removing all implementation of the hooks (build successful).
3
  • it's the useLoading hook. works in dev mode but returns null in production. Commented Oct 4, 2024 at 11:41
  • there are also other factors. Next.js can behave differently due to strict mode or hydration issues, particularly when dealing with contexts. ensure the LoadingProvider is correctly imported in your layout.tsx. check components that rely on the LoadingProvider are marked as client-side components using "use client". these are some of the key points that come up when there are context handling. Commented Oct 4, 2024 at 11:45
  • @burcu I have no clue for the solution, so i switched to a provider-less state management library called Zustand and the project have been build successfully. Anyway I've tried your suggestion, unfortunately that didn't solve the problem, if you're interested to see the whole app source code you can visit this github repository of mine. Thanks for your participations 👋 Commented Oct 4, 2024 at 13:19

1 Answer 1

0

I had a similar problem in Next.js 14.2.5 and tried various methods without success. I ended up downgrading to 14.1.1, and now the build works fine. If you find a solution for version 14.2.5, please share it

Sign up to request clarification or add additional context in comments.

1 Comment

I ended up using a state management library called Zustand which I've mentioned on the comment section above, and it works just fine without changing my Next.js version

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.