在服务器操作中设置Cookie的工作方式
我已经阅读了来自(hlasensky和AnasSafi)[https://stackoverflow.com/questions/76483495/cant-set-cookie-in-server-action-next-js-13-4]的问题和答案,但我必须说,他们是如何做的,甚至是做了什么,都不太清楚(缺乏代码问题和解决方案的例子)
所以,我的问题是。
我有这个服务器动作,它应该创建一个cookie并存储用户首选语言。
'use server';
import { Locale } from "@/lib/translations/i18n.config";
import { cookies } from 'next/headers';
export default async function setLocaleCookie(locale: Locale) {
cookies().set({
name: 'NEXT_LOCALE',
value: locale,
path: '/',
maxAge: 60 * 60 * 24 * 30, // 30 days
})
console.log("NEXT_LOCALE cookie set to:", locale)
}
字符串
接下来,我需要在用户选择其首选语言时调用此函数。
所以,我做了一个组件(最好是客户端,但如果需要,可以转换为服务器)。
(/components/LocaleSwitcher.tsx)
'use client';
import { i18nConfig, Locale } from '@/lib/translations/i18n.config';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Button } from '../ui/button';
import setLocaleCookie from '@/lib/server_actions/cookies/locale';
export default function LocaleSwitcher() {
const pathName = usePathname()
function redirectedPathName(locale: Locale) {
if (!pathName) return '/'
const segments = pathName.split('/')
segments[1] = locale
return segments.join('/')
}
const locales = i18nConfig.locales
return (
<ul className='flex gap-x-3'>
{locales.map(locale => {
return (
<li key={locale}>
<Link
href={redirectedPathName(locale)}
className='rounded-md border bg-black px-3 py-2 text-white'
locale={locale}
>
{locale}
</Link>
<form action={setLocaleCookie(locale)}>
<Button
type="submit"
className='rounded-md border'
>
{locale}
</Button>
</form>
</li>
)
})}
</ul>
)
}
型
此组件位于Header服务器组件内部
(/components/Header.tsx):
/** @format */
import { User, getServerSession } from 'next-auth';
import Logo from './Logo';
import NavigationWeb from './NavigationWeb';
import UserMenu from './UserMenu';
import LocaleSwitcher from './LocaleSwitcher';
import { authOptions } from '@/lib/helpers/authOptions';
import { Locale } from '@/lib/translations/i18n.config';
interface NavbarProps {
user?: User;
locale?: Locale;
}
export default async function Header({ user, locale }: NavbarProps) {
const session = await getServerSession(authOptions);
user = session?.user;
return (
<div className="z-10 border-b py-4 px-16 w-full">
<div className="flex flex-row items-center justify-between gap-3 md:gap-0">
<Logo />
<div className="flex justify-between items-center gap-4">
<NavigationWeb />
<UserMenu user={user} />
<LocaleSwitcher /> // HERE IS THE LOCALE SWITCHER COMPONENT
</div>
</div>
</div>
);
}
型
它本身嵌套在RootLayout**(app/[locale]/layout.ts)**中:
/** @format */
import { Nunito, Inter } from 'next/font/google';
import './globals.css';
import Header from '@/components/header/Header';
import NextAuthSessionProvider from '@/components/providers/SessionProvider';
import { ThemeProvider } from '@/components/providers/ThemeProvider';
import Footer from '@/components/footer/Footer';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/helpers/authOptions';
import localFont from 'next/font/local';
import { Toaster } from '@/components/ui/toaster';
import { i18nConfig, Locale } from '@/lib/translations/i18n.config';
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
const nunito = Nunito({
subsets: ['latin'],
display: 'swap',
variable: '--font-nunito',
});
const gambettaReg = localFont({
src: './fonts/Gambetta-Regular.woff2',
display: 'swap',
variable: '--font-gambetta-reg',
});
const gambettaSemi = localFont({
src: './fonts/Gambetta-Semibold.woff2',
display: 'swap',
variable: '--font-gambetta-semi',
});
const circularBold = localFont({
src: './fonts/CircularXXWeb-Bold.woff2',
display: 'swap',
variable: '--font-circular-bold',
});
export const metadata = {
title: 'App Template',
description: 'A template for Next.js applications',
};
export async function generateStaticParams() {
return i18nConfig.locales.map(locale => ({ locale: locale }))
}
export default async function RootLayout({
children,
params,
}: {
children: React.ReactNode;
params: { locale: Locale };
}) {
const session = await getServerSession(authOptions);
return (
<NextAuthSessionProvider session={session}>
<html lang={params.locale}>
<body
className={`${circularBold.variable} ${gambettaReg.variable} ${gambettaSemi.variable} ${nunito.variable} ${inter.variable} font-inter`}
>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<main className="flex flex-col justify-between items-center min-h-screen min-w-screen">
<Header
user={session?.user}
locale={params.locale}
/>
{children}
<Footer
// locale={params.locale}
/>
<Toaster
// locale={params.locale}
/>
</main>
</ThemeProvider>
</body>
</html>
</NextAuthSessionProvider>
);
}
型
我以为我在Next.js文档方面做得很好。但我总是收到这个错误日志:
Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
at AppContainer (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:341:29)
at AppContainerWithIsomorphicFiberStructure (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:377:57)
at div
at Body (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:677:21)
Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
at AppContainer (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:341:29)
at AppContainerWithIsomorphicFiberStructure (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:377:57)
at div
at Body (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:677:21)
Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
at PathnameContextProviderAdapter (C:\Users\samue\repos\app-template\node_modules\next\dist\shared\lib\router\adapters.js:78:11)
at AppContainer (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:341:29)
at AppContainerWithIsomorphicFiberStructure (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:377:57)
at div
at Body (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:677:21)
Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
at PathnameContextProviderAdapter (C:\Users\samue\repos\app-template\node_modules\next\dist\shared\lib\router\adapters.js:78:11)
at AppContainer (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:341:29)
at AppContainerWithIsomorphicFiberStructure (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:377:57)
at div
at Body (C:\Users\samue\repos\app-template\node_modules\next\dist\server\render.js:677:21)
型
所以我已经尝试了不同的方法.但任何最好的东西给我一个“饼干只能在服务器操作或路由器修改”.但我使用的是服务器操作!
我已经检查了Next.js issue 51875上的讨论,但我看不出这对我有什么帮助?
我做错了什么?
1条答案
按热度按时间idfiyjo81#
TLDR:你必须在客户端组件中调用你的服务器操作。注意:这些代码片段不会在客户端组件中运行。
字符串
型