javascript - När man kör en Next.js-applikation i utvecklingsläge uppstår ett körtidsfel som säger "ReferenceError: Cannot access X before initialization"


Jag använder next.js version 13.4. Jag skapade en Provider med hjälp av ContextAPI i react (säg att det är AuthContext) och omsluter hela applikationen med den i RootLayout-komponenten. RootLayout är placerad i app/layout.tsx.

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>
        <GlobalErrorBoundary>
          <AuthProvider>{children}</AuthProvider>
        </GlobalErrorBoundary>
      </body>
    </html>
  );
}

Det finns inget fel vid byggtid men när jag kör npm run dev, skrek webbläsaren att "Ohanterat körtidsfel" uppstår. Och säger, "ReferenceError: Kan inte komma åt 'AuthContext' innan initialisering".

När jag bygger applikationen och npm run start, fungerar det bra. Det händer bara när jag kör npm run dev. Vad som är värre är att detta körfel händer slumpmässigt, ganska ofta, dock.

När jag tittar i Reacts devTool finns det ett fel i ReactDevOverlay, som har ett barn som heter <DevRootNotFoundBoundary />. Felmeddelandet säger: "Ovanstående fel uppstod i komponenten".

Redigera:

Här är en enkel version av Auth.tsx (för att deklarera ContextAPI) koden:

"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;
};

Du kanske vill veta insidan av useStateWithLocalStorage som används ovan. De möjliga fel som uppstår när man refererar till localStorage på servern täcks av nedanstående logik.

if (typeof window !== "undefined") {
    return localStorage.getItem(key);
}

Redigera:

Jag hittade en misstänkt punkt i kodbasen, men kan inte lista ut den exakta orsaken till den. Kan någon hjälpa mig med detta?

Min Auth.tsx-fil finns under katalogen app/contexts/withLocalStorage/. Inuti denna katalog finns det 2 olika Context-filer utöver Auth.tsx-filen och dessutom en index.ts-fil. Alla variabler i Context-filerna exporteras genom index.ts.

Nedan är index.ts.

"use client";

export * from "./Example1";
export * from "./Example2";
export * from "./Auth";

Den enda skillnaden i Auth och de andra 2 exempel-filerna är att i Auth.tsx används useEffect och useMemo. När jag kommenterar ut raden ovanför export * from "./Auth"; i index.ts, FÖRSVINNER FELET!

Det verkar som att index.ts försöker importera moduler på serversidan. Men en Context-fil som använder Reacts klient-sidans API har ännu inte skapats vid den tiden. "use client";-direktivet i index.ts fungerar inte i det här fallet. Men varför? Eller om så är fallet, finns det någon lösning för att använda useEffect eller useMemo i context-filer?