NextJS 13(App Router):如何从Middleware向组件传递数据?
解决Next.js 13 App Router中Middleware向组件传递语言标识的问题
问题根源
你用Middleware设置Cookie后,组件首次加载无法读取的原因是:Cookie通过响应头的Set-Cookie字段下发给浏览器,浏览器只有收到完整响应后才会存储该Cookie。而首次渲染时(无论服务端还是客户端),组件读取的是请求阶段的Cookie,此时新Cookie还未被浏览器写入,自然拿不到;只有刷新后,请求头才会带上这个Cookie,组件才能读取。
下面是几个无需刷新就能直接传递语言标识的方案:
方案一:通过自定义响应头传递(推荐,支持服务端/客户端组件)
Middleware可以在响应中添加自定义HTTP头,组件能直接从请求头中读取该值,无需等待Cookie写入。
修改Middleware代码
import { NextResponse } from 'next/server' export const middleware = (req) => { const pathname = req.nextUrl.pathname const language = pathname.split('/')[1] const allowedLanguages = ['en', 'de']; if(allowedLanguages.includes(language)) { const response = NextResponse.rewrite(new URL(pathname.replace(`/${language}`, ''), req.url)) // 添加自定义响应头,替代Cookie response.headers.set('x-language', language) return response } } export const config = { matcher: ['/((?!assets|api|_next/static|favicon.ico).*)'], }
在组件中读取语言标识
服务端组件(无需加'use client')
import { headers } from 'next/headers' export default function Page() { const langHeaders = headers() const language = langHeaders.get('x-language') || 'en' // 设置默认值 return <div>当前语言:{language}</div> }
客户端组件(需加'use client')
'use client' import { useHeaders } from 'next/headers' export default function ClientComponent() { const headers = useHeaders() const language = headers.get('x-language') || 'en' return <div>当前语言:{language}</div> }
方案二:客户端组件直接从URL解析(简单直接)
由于Middleware的rewrite是服务器内部重写,浏览器地址栏仍会保留原始URL(比如/en/asdf/),因此客户端组件可以直接通过Next.js提供的usePathname钩子解析路径中的语言标识,无需依赖Cookie或响应头。
客户端组件代码
'use client' import { usePathname } from 'next/navigation' export default function ClientComponent() { const pathname = usePathname() const language = pathname.split('/')[1] || 'en' // 可选:验证语言是否在允许列表内 const allowedLanguages = ['en', 'de'] const validLang = allowedLanguages.includes(language) ? language : 'en' return <div>当前语言:{validLang}</div> }
方案三:结合服务器组件传递给子组件
如果你的页面是服务器组件,可以先在服务器组件中解析URL(或通过响应头获取语言),再将语言标识作为props传递给下游的客户端/服务器子组件。
服务器组件示例
import { headers } from 'next/headers' import ClientComponent from './ClientComponent' export default function Page() { const langHeaders = headers() const language = langHeaders.get('x-language') || 'en' // 将语言作为props传给子组件 return <ClientComponent language={language} /> }
客户端子组件
'use client' export default function ClientComponent({ language }) { return <div>当前语言:{language}</div> }
内容的提问来源于stack exchange,提问作者pak
相关产品推荐
相关产品推荐

