Next.js 14 App Router服务端与客户端组件混合使用报错求助
Next.js 14 App Router:服务端组件嵌套客户端组件报错问题
我当前使用Next.js v14及App Router,想实现服务端组件嵌套在客户端组件中的需求(官方文档说明支持这种嵌套方式):
<ClientComponent> <ServerComponent /> </ClientComponent>
但实际尝试后始终触发报错:async/await is not yet supported in Client Components, only Server Components。我的核心目标是在服务端组件AllBlogs中完成所有博客文章的获取,当前组件层级定义如下:
- Layout: 服务端组件
- StoryblokProvider: 客户端组件
- Page: 服务端组件
- BlogOverviewPage: 服务端组件
- AllBlogs: 预期为服务端组件
组件树结构:Layout > StoryblokProvider > Page > BlogOverviewPage > AllBlogs
各组件代码
Layout组件
export default async function RootLayout({ children, params: { locale }, }: Props) { return ( <StoryblokProvider> <html lang={locale}> <body> {children} </body> </html> </StoryblokProvider> ) }
StoryblokProvider组件
/** 1. Tag it as a client component */ "use client" import { apiPlugin, storyblokInit } from "@storyblok/react" import { storyblokComponents } from "@/components/storyblok/storyblok-components" /** 2. Initialize it as usual */ storyblokInit({ accessToken: process.env.NEXT_PUBLIC_STORYBLOK_TOKEN, use: [apiPlugin], components: storyblokComponents, }) const StoryblokProvider = ({ children }: { children: React.ReactNode }) => { return children } export default StoryblokProvider
Page组件
const Page = async ({ params }: Props) => { const { data } = await fetchData(params.slug) return ( <> <CaptchaProvider> <StoryblokStory story={data.story} bridgeOptions={bridgeOptions} /> <div id="pewl" /> </CaptchaProvider> </> ) } export default Page async function fetchData(slug: string) { slug = slug ?? "home" if (Array.isArray(slug)) { slug = slug.join("/") } const storyblokApi: StoryblokClient = getStoryblokApi() return storyblokApi.getStory(slug) }
AllBlogs组件
const AllBlogs = async () => { const blogs = await fetchAllBlogs() return blogs.map((blog: BlogPageStoryblok) => ( <BlogCard blog={blog} key={blog.uuid} /> )) } const fetchAllBlogs = cache(async () => { let sbParams: ISbStoriesParams = { starts_with: "blog", } const storyblokApi: StoryblokClient = getStoryblokApi() const { data } = await storyblokApi.get("cdn/stories/", sbParams) return data.stories.filter( (story: StoryblokStory<BlogPageStoryblok>) => !story.is_startpage ) })
尝试过的解决方法
我曾尝试将AllBlogs包裹在自定义的客户端组件中,但仍触发相同报错:
"use client" export default function ClientComponent({ children, }: { children: React.ReactNode }) { return <> {children} </> }
const BlogOverviewPage = ({ blok }: any) => { return ( <ClientComponent> <AllBlogs /> </ClientComponent> ) }
更新测试结果
如果在Page.tsx中用AllBlogs替换StoryblokStory,博客内容可以正常在服务端获取,但其他页面均无法正常工作:
const Page = async ({ params }: Props) => { const { data } = await fetchData(params.slug) return ( <CaptchaProvider> <BlogOverviewPage blok={data.story} /> {/*<StoryblokStory story={data.story} bridgeOptions={bridgeOptions} />*/} <div id="pewl" /> </CaptchaProvider> ) } export default Page async function fetchData(slug: string) { slug = slug ?? "home" if (Array.isArray(slug)) { slug = slug.join("/") } const storyblokApi: StoryblokClient = getStoryblokApi() return storyblokApi.getStory(slug) }
希望得到解决该报错的方案,实现服务端组件嵌套在客户端组件中获取博客的需求。
内容的提问来源于stack exchange,提问作者combi35
相关产品推荐
相关产品推荐

