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

Next.js 13导航栏报错:客户端组件不支持async/await,求解决

解决Next.js 13客户端组件中引入async组件的错误

错误原因

标记了"use client"的Navbar组件(客户端组件)无法直接渲染async函数组件。Next.js 13中,async函数组件默认属于服务器组件,客户端组件不支持嵌套渲染异步服务器组件——因为客户端环境无法处理组件级别的async/await逻辑。


方案1:将async组件转为服务器组件,通过动态导入使用

该方案保留服务器端数据获取的优势(缓存、预渲染),适合需要服务器端预加载数据的场景。

步骤:

  1. 确保DataManufactureNav组件没有添加"use client"标记,保持它作为异步服务器组件(你的现有代码已经满足这一点)。
  2. 在navbar.tsx顶部添加动态导入代码:
    import dynamic from 'next/dynamic';
    
    // 动态导入服务器组件,ssr设为true确保在服务器端完成渲染
    const DataManufactureNav = dynamic(() => import('./path-to/DataManufactureNav'), { ssr: true });
    
  3. Navbar中使用<DataManufactureNav />的代码无需修改,直接保留即可。

方案2:将async组件转为客户端组件,用客户端数据获取逻辑

如果不需要服务器端预渲染数据,可以把DataManufactureNav改成客户端组件,在客户端用useEffect获取数据:

修改DataManufactureNav代码:

"use client";
import { useEffect, useState } from 'react';
import Link from 'next/link';

function DataManufactureNav() {
  const [data, setData] = useState<categoriesDTO[] | []>([]);
  const [isError, setIsError] = useState(false);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const fetchCategories = async () => {
      try {
        const res = await fetch("http://localhost:8081/product/categories", {
          next: { revalidate: 3600 },
        });
        if (res.ok) {
          const categories = await res.json();
          setData(categories);
        } else {
          setIsError(true);
        }
      } catch (err) {
        setIsError(true);
      } finally {
        setIsLoading(false);
      }
    };

    fetchCategories();
  }, []);

  if (isLoading) return <div>加载中...</div>;
  if (isError) return <div>加载出错</div>;

  return (
    <>
      {data.length > 0 ? (
        data.map(item => (
          <li key={item.CATEGORY_ID}>
            <Link className="nav-link" href={`/categories/${item.CATEGORY_ID}`}>
              {item.CATEGORY_NAME}
            </Link>
          </li>
        ))
      ) : (
        <div>暂无数据</div>
      )}
    </>
  );
}

export default DataManufactureNav;

修改后,DataManufactureNav成为客户端组件,可直接在Navbar中导入使用,无需额外配置。


方案3:拆分组件为服务器端数据获取+客户端渲染

该方案分离数据获取与渲染逻辑,服务器组件负责获取数据,客户端组件负责渲染:

  1. 创建服务器组件ManufactureNavServer.tsx,负责获取数据:

    import dynamic from 'next/dynamic';
    // 动态导入客户端渲染组件
    const ManufactureNavClient = dynamic(() => import('./ManufactureNavClient'), { ssr: false });
    
    async function ManufactureNavServer() {
      let data: categoriesDTO[] | [] = [];
      const res = await fetch("http://localhost:8081/product/categories", {
        next: { revalidate: 3600 },
      });
      if (res.ok) {
        data = await res.json();
      }
      // 将获取到的数据传给客户端组件
      return <ManufactureNavClient data={data} />;
    }
    
    export default ManufactureNavServer;
    
  2. 创建客户端组件ManufactureNavClient.tsx,负责渲染:

    "use client";
    import Link from 'next/link';
    
    export default function ManufactureNavClient({ data }: { data: categoriesDTO[] | [] }) {
      return (
        <>
          {data.length > 0 ? (
            data.map(item => (
              <li key={item.CATEGORY_ID}>
                <Link className="nav-link" href={`/categories/${item.CATEGORY_ID}`}>
                  {item.CATEGORY_NAME}
                </Link>
              </li>
            ))
          ) : (
            <div>暂无数据</div>
          )}
        </>
      );
    }
    
  3. 在navbar.tsx中导入并使用服务器组件:

    import dynamic from 'next/dynamic';
    const ManufactureNavServer = dynamic(() => import('./ManufactureNavServer'), { ssr: true });
    
    // 在Navbar的JSX中替换原<DataManufactureNav />为:
    <ManufactureNavServer />
    

内容的提问来源于stack exchange,提问作者Frank

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:10:55