我正在使用
@clerk/nextjs": "^4.29.5"
作为我的 next.js 14
应用程序的身份验证系统。我正在使用 context-api 管理一些全局状态。我的问题是,当我重新访问我的主路线 (/) 时,页面完全重新加载,而不是软导航(其他路线都可以)。这仅发生在托管的 (vercel)
应用程序中,而不是在本地主机中,甚至当我使用 npm start
运行构建版本时。如何解决这个问题?我在这里做错了什么?我不想重新加载整个页面。
项目结构:
app/
(auth)
layout.tsx
sign-in/
sign-up/
(root)
layout.tsx
page.tsx
layout.tsx
布局.ts:
import { MainContextProvider } from "@/contexts/MainContext";
import ClerkThemeProvider from "@/lib/providers/ClerkThemeProvider";
import { Suspense } from "react";
import MainPageFallback from "@/components/shared/MainPageFallback";
import { Toaster } from "@/components/ui/toaster";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className={`${inter.className}`}>
<MainContextProvider>
<Suspense fallback={<MainPageFallback />}>
<ClerkThemeProvider>{children}</ClerkThemeProvider>
</Suspense>
</MainContextProvider>
<Toaster />
</body>
</html>
);
}
/contexts/MainContext.ts:
"use client";
import { createContext, useEffect, useState } from "react";
export const MainContext = createContext({
lang: "",
theme: "",
sidebarOpen: false,
handleLang: () => {},
changeTheme: () => {},
closeSidebar: () => {},
openSidebar: () => {},
});
export const MainContextProvider = ({ children }: { children: React.ReactNode }) => {
const [lang, setLang] = useState("en");
const [theme, setTheme] = useState("light");
const [sidebarOpen, setSidebarOpen] = useState(false);
useEffect(() => {
const savedTheme = localStorage.getItem("theme");
const savedLang = localStorage.getItem("lang");
setLang(savedLang ? savedLang : "en");
setTheme(savedTheme ? savedTheme : "light");
}, []);
useEffect(() => {
localStorage.setItem("lang", lang);
document.documentElement.lang = lang;
}, [lang]);
useEffect(() => {
localStorage.setItem("theme", theme);
if (theme === "dark") {
document.body.classList.add("dark");
} else {
document.body.classList.remove("dark");
}
}, [theme]);
const handleLang = () => {
setLang(lang === "en" ? "bn" : "en");
};
const changeTheme = () => {
setTheme(theme === "light" ? "dark" : "light");
};
const openSidebar = () => {
setSidebarOpen(true);
};
const closeSidebar = () => {
setSidebarOpen(false);
};
return (
<MainContext.Provider
value={{
lang,
theme,
sidebarOpen,
handleLang,
openSidebar,
changeTheme,
closeSidebar,
}}
>
{children}
</MainContext.Provider>
);
};
/lib/providers/ClerkThemeProvider.tsx
"use client";
import { MainContext } from "@/contexts/MainContext";
import { ClerkProvider } from "@clerk/nextjs";
import { dark } from "@clerk/themes";
import { useContext } from "react";
export default function ClerkThemeProvider({ children }: { children: React.ReactNode }) {
const { theme } = useContext(MainContext);
return (
<ClerkProvider appearance={{ baseTheme: theme === "dark" ? dark : undefined }}>
{children}
</ClerkProvider>
);
}
中间件.ts
import { authMiddleware } from "@clerk/nextjs";
export default authMiddleware({
// An array of public routes that don't require authentication.
publicRoutes: ["/", "/about", "/contact", "/api/webhooks(.*)", "/api/uploadthing"],
// An array of routes to be ignored by the authentication middleware.
ignoredRoutes: ["/api/webhooks(.*)"],
});
export const config = {
matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};
我解决了这个问题。我想分享它。这是一个简单的原因,为什么主路由总是在部署的版本上完全重新加载。这不是
clerk
软件包原因。
我只需在
loading.tsx
文件夹中添加一个 app/
文件,然后就不会再发生完全重新加载。