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

如何将服务器端外部API数据传递给客户端Mapbox组件?

解决方案

直接在客户端组件mapbox.tsx里调用服务端的Build_And_Fetch函数会触发CORS错误——因为客户端组件在浏览器环境中运行,直接请求外部API会受浏览器跨域策略限制;而Build_And_Fetch原本是在服务端执行的,服务端请求外部API不受浏览器CORS约束。

下面是两种可行的解决方法:

方法一:服务端预取数据,通过Props传递给客户端组件

在服务端组件(比如页面文件page.tsx)中调用Build_And_Fetch获取数据,再将数据作为props传给客户端组件MapboxMap:

// app/page.tsx(服务端组件,无需加"use client")
import MapboxMap from './mapbox';
import { Build_And_Fetch } from './data';

export default async function Home() {
  const weatherData = await Build_And_Fetch();
  
  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <MapboxMap jsondata={weatherData} />
    </div>
  );
}

修改mapbox.tsx的props定义,确保正确接收数据:

// mapbox.tsx
"use client"
import * as React from "react";
import mapboxgl, { Map } from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";

// 替换原props定义,建议用更具体的类型代替any
const MapboxMap = ({ jsondata }: { jsondata?: any }) => {
  const [map, setMap] = React.useState<mapboxgl.Map>();
  const mapNode = React.useRef(null);
  mapboxgl.accessToken = "pk.eyJ1IjoiY2djdHNjaWVuY2VjZW50ZXIiLCJhIjoiY2xpM2dld3AzMGJkbTNlcGZ2aHowajZncCJ9.vFc7nroP3Pa0Cg7KAxvZjw";

  React.useEffect(() => {
    const node = mapNode.current;
    if(typeof window === "undefined" || node === null) return;

    const mapboxMap = new mapboxgl.Map({
      container: node,
      style: "mapbox://styles/mapbox/light-v11",
      center: [-72,41],
      zoom:0.6
    });
    setMap(mapboxMap);

    mapboxMap.on('load', () => {
      if (!jsondata) return;
      // 使用传入的jsondata作为数据源
      mapboxMap.addSource("weather-data",{
        "type":"geojson",
        "data": jsondata
      });
      // 可在此添加图层渲染逻辑
    });

    return () => {mapboxMap.remove()};
  }, [jsondata]); // 添加jsondata作为依赖,数据更新时重新处理地图

  return <div ref={mapNode} style={{width:"100%",height:"100%"}}/>;
}
export default MapboxMap

方法二:创建内部API路由,客户端请求该路由获取数据

在app/api/weather/route.ts创建API路由,在路由内部调用Build_And_Fetch:

// app/api/weather/route.ts
import { Build_And_Fetch } from '@/app/data';
import { NextResponse } from 'next/server';

export async function GET() {
  try {
    const data = await Build_And_Fetch();
    return NextResponse.json(data);
  } catch (error) {
    return NextResponse.json({ error: 'Failed to fetch weather data' }, { status: 500 });
  }
}

然后在mapbox.tsx中请求这个内部API:

// mapbox.tsx
"use client"
import * as React from "react";
import mapboxgl, { Map } from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";

const MapboxMap = () => {
  const [map, setMap] = React.useState<mapboxgl.Map>();
  const [weatherData, setWeatherData] = React.useState<any>(null);
  const mapNode = React.useRef(null);
  mapboxgl.accessToken = "pk.eyJ1IjoiY2djdHNjaWVuY2VjZW50ZXIiLCJhIjoiY2xpM2dld3AzMGJkbTNlcGZ2aHowajZncCJ9.vFc7nroP3Pa0Cg7KAxvZjw";

  // 获取数据
  React.useEffect(() => {
    const fetchData = async () => {
      const res = await fetch('/api/weather');
      const data = await res.json();
      setWeatherData(data);
    };
    fetchData();
  }, []);

  React.useEffect(() => {
    const node = mapNode.current;
    if(typeof window === "undefined" || node === null || !weatherData) return;

    const mapboxMap = new mapboxgl.Map({
      container: node,
      style: "mapbox://styles/mapbox/light-v11",
      center: [-72,41],
      zoom:0.6
    });
    setMap(mapboxMap);

    mapboxMap.on('load', () => {
      mapboxMap.addSource("weather-data",{
        "type":"geojson",
        "data": weatherData
      });
      // 添加图层渲染逻辑
    });

    return () => {mapboxMap.remove()};
  }, [weatherData]);

  return <div ref={mapNode} style={{width:"100%",height:"100%"}}/>;
}
export default MapboxMap

两种方法对比:

  • 方法一适合需要预渲染数据的场景,页面加载时已获取数据,SEO友好。
  • 方法二更适合动态刷新数据的场景,比如用户触发操作后重新获取数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:02:05