Next.js 13应用目录用async/await取数触发React子元素无效错误
问题原因及解决方案
核心错误原因
你在Page组件顶部添加了'use client',但Next.js 13 app目录中异步Page组件必须是服务器组件——React目前不支持将客户端组件定义为async函数,直接在组件顶层返回Promise就会触发你看到的"Objects are not valid as a React child"错误。
解决方案分两种场景
场景1:页面无需客户端交互(仅渲染数据)
直接移除'use client',保留异步Page组件的写法即可。这是Next.js推荐的服务器端数据获取方式,数据会在服务器端预取完成后再渲染HTML,性能更优。
修改后的代码:
async function getProducts() { const { data } = await storefront(productsQuery); return data.products; } export default async function Page({ params }: any) { const fetchedData = await getProducts(); return (<> {fetchedData.edges.map((item: any) => ( <Text key={item.node.title}>{item.node.title}</Text> ))} </>); }
注意:给map循环的元素添加唯一key属性,这是React渲染列表的规范要求。
场景2:页面需要客户端交互(如Chakra UI交互组件)
如果必须使用客户端组件(比如需要处理点击、状态等交互逻辑),则需要将异步数据获取逻辑移到useEffect钩子或专用数据获取库(如SWR、React Query)中,不能直接在组件顶层使用await。
用useEffect实现的示例:
'use client'; import { useEffect, useState } from 'react'; import { Text } from '@chakra-ui/react'; async function getProducts() { const { data } = await storefront(productsQuery); return data.products; } export default function Page({ params }: any) { const [productEdges, setProductEdges] = useState<any[]>([]); useEffect(() => { const fetchData = async () => { const fetchedData = await getProducts(); setProductEdges(fetchedData.edges); }; fetchData(); }, []); return (<> {productEdges.map((item: any) => ( <Text key={item.node.title}>{item.node.title}</Text> ))} </>); }
用SWR实现(推荐,自带缓存、重新验证能力):
'use client'; import useSWR from 'swr'; import { Text } from '@chakra-ui/react'; const fetcher = async () => { const { data } = await storefront(productsQuery); return data.products.edges; }; export default function Page({ params }: any) { const { data: productEdges, error } = useSWR('products', fetcher); if (error) return <Text>加载商品失败</Text>; if (!productEdges) return <Text>加载中...</Text>; return (<> {productEdges.map((item: any) => ( <Text key={item.node.title}>{item.node.title}</Text> ))} </>); }
关键知识点
- app目录中,服务器组件(无
'use client')支持async/await顶层数据获取,无需状态管理 - 客户端组件(加
'use client')不能定义为async函数,必须通过钩子或数据库处理异步逻辑 - Chakra UI的纯展示组件可以直接在服务器组件中使用,仅当需要客户端交互时才需要标记
'use client'
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

