You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:52:37