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

NextJS14客户端组件用useState遇async/await不支持错误求助

问题解决:NextJS 14.03 客户端组件 async/await 报错

错误原因

你遇到的核心问题是客户端组件上下文被服务器组件污染:虽然给SectionGridHasMap加了"use client",但它导入的子组件(如Heading2、TabFilters、Pagination、EventCard)如果是未标记"use client"的服务器组件,Next.js会强制将整个SectionGridHasMap当作服务器组件处理。而服务器组件既不能使用useState这类客户端钩子,也不允许在组件上下文内触发异步逻辑冲突,最终导致报错。

解决方案

方案一:统一客户端组件标记

给所有被SectionGridHasMap导入的子组件顶部添加"use client"指令:

  • @/shared/Pagination.tsx
  • @/shared/Heading2.tsx
  • ./TabFilters.tsx
  • @/components/cards/event-card.tsx

客户端组件只能导入其他客户端组件,直接引用服务器组件会破坏Next.js的组件上下文隔离机制。

方案二:服务器端取数,props传递给客户端组件

将数据获取逻辑移到父页面(服务器组件,无需"use client"),再把数据通过props传给客户端组件,彻底避免客户端组件的异步取数冲突:

修改父页面src/app/(stay-listings)/listing-stay-map/page.tsx:

import React from "react";
import SectionGridHasMap from "../SectionGridHasMap";

const ListingStayMapPage = async () => {
  // 服务器组件顶层直接执行fetch,Next.js会自动优化请求
  const res = await fetch("http://localhost:3000/api/events", {
    cache: "no-store",
  });

  if (!res.ok) {
    throw new Error("Failed to fetch events");
  }

  const { events } = await res.json();

  return (
    <div className="container pb-24 lg:pb-28 2xl:pl-10 xl:pr-0 xl:max-w-none">
      <SectionGridHasMap events={events} />
    </div>
  );
};

export default ListingStayMapPage;

修改子组件src/app/(stay-listings)/SectionGridHasMap.tsx:

"use client";
import React, { useState } from 'react';
import GoogleMapReact from 'google-map-react';
import Pagination from "@/shared/Pagination";
import TabFilters from "./TabFilters";
import Heading2 from "@/shared/Heading2";
import EventCard from "@/components/cards/event-card";

const defaultMapProps = {
  center: {
    lat: 59.95,
    lng: 30.33
  },
  zoom: 11
};

const SectionGridHasMap = ({ className = "", events: initialEvents }) => {
  // 用服务器端传来的数据初始化状态,后续可正常修改
  const [events, setEvents] = useState(initialEvents || []);

  return (
    <div className="relative flex min-h-screen">
      <div className={`nc-SectionGridFilterCard flex-1 ${className}`} data-nc-id="SectionGridFilterCard">
        <Heading2 />
        <div className="mb-8 lg:mb-11">
          <TabFilters />
        </div>
        <div className="grid grid-cols-1 gap-6 md:gap-8 sm:grid-cols-2 lg:grid-cols-3">
          {/* 优先用MongoDB文档的_id作为key,避免index导致的渲染问题 */}
          {events.map((event) => (
            <EventCard key={event._id} event={event} />
          ))}
        </div>
        <div className="flex mt-16 justify-center items-center">
          <Pagination />
        </div>
      </div>

      <div className="w-full h-full lg:w-1/2">
        <GoogleMapReact
          bootstrapURLKeys={{ key: 'GOOGLE_MAPS_API_KEY' }}
          defaultCenter={defaultMapProps.center}
          defaultZoom={defaultMapProps.zoom}
        />
      </div>
    </div>
  );
};

export default SectionGridHasMap;

额外检查

确保你的/api/events路由返回格式正确({ events: [...] }),且路由本身没有逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:57:12