我试图使用layout.tsx
在app
目录下的Next.js 13有一个导航布局,是目前在所有的页面。我设法使它,当用户注销/登录,导航栏的变化,但问题是,我必须刷新页面(F5)看到导航栏上的变化。我认为这个问题是有关的该高速缓存,这就是为什么我尝试使用export const dynamic = 'force-dynamic'
。
我还将客户端组件添加到服务器组件,因为我认为这会是问题所在,但它并没有解决问题。我想使用export const dynamic = 'force-dynamic'
来处理该高速缓存,但现在我遇到了一个似乎无法解决的错误。我得到的错误消息是:
错误
Only async functions are allowed to be exported in a "use server" file.
字符串
下面是详细的错误跟踪:
./app/components/ClientInsideServerLayout.tsx
Error:
x Only async functions are allowed to be exported in a "use server" file.
,-[C:\Users\zantl\OneDrive\Documentos\GitHub\sssss\gestion-gastos-supabase\app\components\ClientInsideServerLayout.tsx:2:1]
2 |
3 | import { getSessionStatus } from "../ServerActions/isUserLoggedIn";
4 | import ClientLayout from "./ClientLayout"
5 | export const dynamic = 'force-dynamic'
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6 |
7 | export async function ClientInsideServerLayout() {
7 | const isLoggedIn = await getSessionStatus();
`----
型
代码
下面是导致错误的每个相关文件的代码:
文件:ClientInsideServerLayout.tsx
'use server';
import { getSessionStatus } from "../ServerActions/isUserLoggedIn";
import ClientLayout from "./ClientLayout"
export const dynamic = 'force-dynamic'
export async function ClientInsideServerLayout() {
const isLoggedIn = await getSessionStatus();
return (
<>
<ClientLayout isLoggedIn={isLoggedIn}></ClientLayout>
</>
)
}
型
文件:ClientLayout.tsx
'use client'
import Link from 'next/link';
import { useRouter } from 'next/navigation'
export default function ClientLayout({ isLoggedIn }: { isLoggedIn: boolean }) {
const router = useRouter();
const signOut = async () => {
try {
const response = await fetch("http://localhost:3000/auth/sign-out", {
method: "POST"
});
if (response.ok) {
router.push("/")
console.log('The resource has been permanently moved.');
}
} catch (error: unknown) {
console.error('An error occurred:', error);
}
};
const logIn = () =>{
router.push("/login")
}
return (
<nav className="flex items-center justify-between flex-wrap bg-teal-500 p-6">
<div className="flex items-center flex-shrink-0 text-white mr-6">
{/* ... logo code ... */}
</div>
<div className="block lg:hidden">
{/* ... button code ... */}
</div>
<div className="w-full block flex-grow lg:flex lg:items-center lg:w-auto">
<div className="text-sm lg:flex-grow">
<Link href="/ingresos" passHref>
<span className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white">
Ingresos
</span>
</Link>
</div>
<div>
{isLoggedIn ? (
<button onClick={signOut} className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white lg:mt-0">Log Out</button>
) : (
<>
<button onClick={logIn} className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white lg:mt-0 mr-2">Log In</button>
<button className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white lg:mt-0">Sign Up</button>
</>
)}
</div>
</div>
</nav>
);
}
型
下面是我使用的RootLayout
的代码:
// Existing RootLayout code
'use server';
import './globals.css';
import { getSessionStatus } from './ServerActions/isUserLoggedIn';
import { ClientInsideServerLayout } from './components/ClientInsideServerLayout';
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const isLoggedIn = await getSessionStatus();
return (
<html lang="en">
<body>
<div>
<ClientInsideServerLayout></ClientInsideServerLayout>
{children}
</div>
</body>
</html>
);
}
型
下面是上下文的目录结构:
app/
auth/
callback/
route.ts
sign-in/
route.ts
sign-out/
route.ts
sign-up/
route.ts
components/
ClientInsideServerLayout.tsx
ClientLayout.tsx
Login.tsx
tablaIngresos.tsx
ingresos/
page.tsx
login/
messages.tsx
page.tsx
ServerActions/
isUserLoggedIn.ts
_examples/
client-component/
page.tsx
route-handler/
route.ts
server-action/
page.tsx
server-component/
page.tsx
auth-form.tsx
favicon.ico
globals.css
layout.tsx
page.tsx
components/
LogoutButton.tsx
NextJsLogo.tsx
SupabaseLogo.tsx
types/
supabase.ts
.env.local
.gitignore
middleware.ts
next-env.d.ts
next.config.js
package-lock.json
package.json
postcss.config.js
README.md
tailwind.config.js
tsconfig.json
型
提问
有人能解释一下为什么会发生这个错误吗?我如何修复它,同时在单击注销按钮时保持布局更新功能?我想在不刷新页面的情况下实现这一点。
任何见解或建议将不胜感激!谢谢!
2条答案
按热度按时间y53ybaqx1#
"use server"
标签不能用于将组件在服务器端渲染为"use client"
。它应该与Server Actions一起使用。如果您在文件的顶部添加"use server"
,则只能从中导出async
函数:字符串
顶部没有
"use client"
的组件是服务器组件,因此从ClientInsideServerLayout.tsx
和RootLayout.tsx
中删除'use server'
。现在,您必须手动刷新页面以反映注销状态的事实可以在
router.refresh()
的帮助下处理:型
有关为什么使用
router.refresh()
的更多信息,请查看来自Next.js的Tim Neutkens的article。yebdmbv42#
我在接下来的14中遇到了一个类似的问题,我使用index.ts文件来集中服务器操作的导出。问题是我需要从index.ts文件本身删除
'use server'
。错误:
字符串
正确:从文件顶部删除使用服务器。
型
评论服务器操作示例
型
正确地从它导出一个
async
函数,在每个服务器操作文件的顶部使用use server
。希望这对某人有帮助。