Next.js中服务端组件与客户端组件结合调用的问题求助
解决Next.js客户端组件调用异步服务端组件的报错问题
问题原因
你在带'use client'的客户端组件SentenceDisplayMng中直接调用了异步服务端组件SentenceList,但客户端组件不支持定义为async的组件,Next.js在客户端渲染阶段无法处理这种async组件,因此抛出async/await is not yet supported in Client Components错误。
正确实现方式
方案1:用Suspense包裹服务端组件(推荐,保留服务端组件优势)
服务端组件保持异步逻辑,客户端组件通过Suspense包裹服务端组件,同时传递参数,当客户端state变化时,服务端组件会重新请求数据并渲染。
修改后的服务端组件SentenceList
export default async function SentenceList({ param }: { param: number }) { // 根据param参数获取对应数据 const theResult = await sentences(param) return <div> { theResult.map(item => ( <div key={item.orderKey as string}> <SentenceUnit sentence={item.sentence} english={item.english} french={item.french} /> </div> )) } </div> }
修改后的客户端组件SentenceDisplayMng
'use client' import { useState } from 'react' import { Suspense } from 'react' import SentenceList from './SentenceList' export default function SentenceDisplayMng() { const [transType, setTransType] = useState(1) const [typeChecks, setTypeChecks] = useState([false,false]) return <div> <TranslatChoice actionFunc={(v) => setTransType(v)} radChecks={typeChecks} /> <Suspense fallback={<div>加载中...</div>}> <SentenceList param={transType} /> </Suspense> </div> }
方案2:客户端组件调用API路由获取数据
如果更倾向于在客户端处理数据获取,可以将服务端的取数逻辑迁移到API路由,客户端通过fetch请求数据并渲染。
1. 创建API路由app/api/sentences/route.js
import { NextResponse } from 'next/server' import { sentences } from '@/path/to/your/sentences/service' export async function GET(request) { const { searchParams } = new URL(request.url) const param = parseInt(searchParams.get('param')) || 1 const data = await sentences(param) return NextResponse.json(data) }
2. 修改客户端组件SentenceDisplayMng
'use client' import { useState, useEffect } from 'react' export default function SentenceDisplayMng() { const [transType, setTransType] = useState(1) const [typeChecks, setTypeChecks] = useState([false,false]) const [sentencesData, setSentencesData] = useState([]) const [loading, setLoading] = useState(true) // 当transType变化时重新请求数据 useEffect(() => { const fetchData = async () => { setLoading(true) const res = await fetch(`/api/sentences?param=${transType}`) const data = await res.json() setSentencesData(data) setLoading(false) } fetchData() }, [transType]) if (loading) return <div>加载中...</div> return <div> <TranslatChoice actionFunc={(v) => setTransType(v)} radChecks={typeChecks} /> <div> {sentencesData.map(item => ( <div key={item.orderKey as string}> <SentenceUnit sentence={item.sentence} english={item.english} french={item.french} /> </div> ))} </div> </div> }
内容的提问来源于stack exchange,提问作者Michel
相关产品推荐
相关产品推荐

