I am using next.js version 13.4. I made a Provider using ContextAPI in react(, let's say it's AuthContext) and wrap the whole application with it in RootLayout component. The RootLayout is placed in app/layout.tsx.
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<GlobalErrorBoundary>
<AuthProvider>{children}</AuthProvider>
</GlobalErrorBoundary>
</body>
</html>
);
}
There's no error in build time but when I run npm run dev, the browser yelled that "Unhandled Runtime Error" occurs. And saying, "ReferenceError: Cannot access 'AuthContext' before initialization".
When I build the application and npm run start, it works well. It only happens when I run npm run dev. What's worse is this runtime error happens randomly, quite often, though.
When I look into the react's devTool, theres' an error in ReactDevOverlay, which has a children named <DevRootNotFoundBoundary />. The error message is saying, "The above error occurred in the component".

Edit:
Here is a simple version of the Auth.tsx (for declaring ContextAPI) code:
"use client";
export const AuthContext =
createContext<AuthContextType | null>(null);
export const AuthProvider = ({
children,
}: PropsWithChildren) => {
const [token, setToken] =
useStateWithLocalStorage<AuthTokenType>("token");
const newToken = useTokenRefresh(token);
useEffect(() => {
if (newToken === undefined) {
return;
}
setToken(newToken);
}, [newToken]);
useMemo(() => {
if (token === null) {
return;
}
addTokenToHttpClient(token);
}, [token]);
return (
<AuthContext.Provider
value={{
token,
setToken,
}}
>
{children}
</AuthContext.Provider>
);
};
export const useAuthContext = () => {
const context: AuthContextType | null = useContext(
AuthContext
);
if (context === null) {
throw new Error();
}
return context;
};
You might want to know the inside of useStateWithLocalStorage used above. The possible errors occuring when referring to localStorage in the server is covered by below logic.
if (typeof window !== "undefined") {
return localStorage.getItem(key);
}
Edit:
I found a suspicious point in codebase, but cannot figure out the exact reason of it. Can anyone help me with this?
My Auth.tsx file is under app/contexts/withLocalStorage/ directory. Inside this directory there are 2 different Context files other than Auth.tsx file and plus, index.ts file. Every variables of Context files are exported through index.ts.
Below is index.ts.
"use client";
export * from "./Example1";
export * from "./Example2";
export * from "./Auth";
The only difference in Auth and other 2 example files is, in Auth.tsx, it's using useEffect and useMemo. When I comment out the line above export * from "./Auth"; in index.ts, the ERROR DISAPPEARS!.
It seems index.ts is trying to import modules in server-side. But a Context file using React's client-side API is not created yet at that time. "use client"; directive in index.ts doesn't work in this case. But why? Or if so, is there any workaround to use useEffect or useMemo in context files?