NextJS13中'Objects are not valid as a React child'错误排查咨询
错误原因与修复方案
错误原因
ProfileSection是一个使用async/await的异步组件,但你的SettingsPageOrchestrator标记了'use client'属于客户端组件。在Next.js中,只有服务器组件允许用async/await直接获取数据,客户端组件里直接渲染异步组件会返回Promise,而React无法将Promise作为子元素渲染,因此抛出Objects are not valid as a React child (found: [object Promise])错误。
另外,ProfileSection里使用的getServerSession是服务器端方法,无法在客户端组件中运行,这也是潜在问题。
修复方案1:将ProfileSection作为服务器组件使用(推荐)
因为ProfileSection依赖服务器端会话和API调用,更适合作为服务器组件。只需修改客户端组件的导入方式,用next/dynamic动态导入服务器组件:
修改SettingsPageOrchestrator的代码:
'use client' import React, { useState } from 'react' import AnimatedDiv from '../../../(shop)/(components)/animatedDiv' import dynamic from 'next/dynamic' // 动态导入服务器组件,确保SSR启用 const ProfileSection = dynamic(() => import('./profileSection'), { ssr: true }) const AccountSection = dynamic(() => import('./accountSection'), { ssr: true }) const SubscriptionSection = dynamic(() => import('./subscriptionSection'), { ssr: true }) const SettingsPageOrchestrator = () => { const [renderedSection, setRenderedSection] = useState('Profile') return ( <div > <div > <button onClick={() => setRenderedSection('Profile')} > Profile </button> <button onClick={() => setRenderedSection('Account')} > Account </button> <button onClick={() => setRenderedSection('Subscription')} > Subscription and billing </button> </div> <InnerSection section={renderedSection} /> </div> ) } const InnerSection = ({ section }) => { return ( <div> {section === 'Profile' && ( <AnimatedDiv> <ProfileSection /> </AnimatedDiv> )} {section === 'Account' && ( <AnimatedDiv> <AccountSection /> </AnimatedDiv> )} {section === 'Subscription' && ( <AnimatedDiv> <SubscriptionSection /> </AnimatedDiv> )} </div> ) } export default SettingsPageOrchestrator
ProfileSection的代码不需要修改,保持原样即可(确保它没有'use client'标记)。
修复方案2:将ProfileSection改为客户端组件
如果必须将ProfileSection作为客户端组件,需要移除async/await,改用useEffect和useState处理异步数据,同时替换服务器端的getServerSession为客户端的getSession:
修改ProfileSection的代码:
'use client' import React, { useState, useEffect } from 'react' import ProfileContent from './profileContent' import ProfileSkeletron from './profileSkeletron' import { SETTINGS_PROFILE_USER } from '../../../../apiUtils/costants' import { getAuthenticatedServerSide } from '../../../../apiUtils/utils' import { getSession } from 'next-auth/react' const ProfileSection = () => { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) useEffect(() => { const fetchProfileData = async () => { const session = await getSession() const fetchedData = await getAuthenticatedServerSide( session?.user?.access_token, SETTINGS_PROFILE_USER ) setData(fetchedData) setLoading(false) } fetchProfileData() }, []) // 加载状态显示骨架屏 if (loading) { return <ProfileSkeletron /> } return ( <div> <ProfileContent data={data} /> </div> ) } export default ProfileSection
内容的提问来源于stack exchange,提问作者Valentino Fabris Valenti
相关产品推荐
相关产品推荐

