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

如何正确导出MongoDB事件坐标数组至Google Maps组件?

问题分析与修复方案

你的问题核心在于全局变量无法触发React组件的重新渲染,而且组件初始化时异步数据还未加载完成,导致MapsComponent拿到的是空数组。以下是具体的修复方案:

问题根源

  1. 全局变量locArray更新后,React不会自动通知MapsComponent重新渲染,组件始终停留在初始化时的空数组状态。
  2. 组件间数据传递违背了React的单向数据流原则,依赖全局变量会导致状态难以追踪和维护。

修复方案:状态提升到父组件

将数据获取逻辑统一放在父组件中,通过props将坐标数组传递给MapsComponent,确保数据变化时组件能自动更新。

步骤1:改造Listings组件,去掉全局变量

让Listings组件接收父组件传递的listings数据,不再自行处理API请求:

import List from '@mui/material/List';
import Paper from '@mui/material/Paper';
import Grid from '@mui/material/Grid'
import Divider from '@mui/material/Divider';
import React from 'react';
import { Box } from '@mui/material';

export default function Listings({ listings, setFeaturedPosts }) {
  const updateFeaturedPost = (index, updatedPost) => {
    setFeaturedPosts((prevPosts) => {
      const newPosts = [...prevPosts];
      newPosts[index] = updatedPost;
      return newPosts;
    });
  };

  return (
    <React.Fragment>
      <Box elevation={0} style={{ height: '70vh', overflow: 'auto' }}>
        <List>
          {listings &&
            listings.map((listing, index) => {
              const { orgname, title, date, description, startTime, endTime } = listing;
              return (
                <React.Fragment key={listing._id}>
                  <Paper elevation={4} style={{ width: '300px', p: 2, padding: '20px', marginBottom: '20px' }}>
                    <Grid>
                      {orgname}
                      {title} {date}
                      {description}
                      {startTime}
                      {endTime}
                    </Grid>
                  </Paper>
                  <Divider />
                </React.Fragment>
              );
            })}
        </List>
      </Box>
    </React.Fragment>
  );
}

步骤2:创建父组件统一管理数据

在父组件中完成API请求,将listings数据分别传递给Listings和MapsComponent:

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import dayjs from 'dayjs';
import Listings from './Listings';
import MapsComponent from './MapsComponent';
import { Grid } from '@mui/material';

export default function EventsPage({ setFeaturedPosts }) {
  const [listings, setListings] = useState(null);

  async function retrieveListings() {
    try {
      const res = await axios.post('http://localhost:5000/getevents', {
        loc: JSON.parse(localStorage.getItem('location')),
        nEvents: 10,
        startdate: dayjs().startOf('day'),
        enddate: dayjs().endOf('day'),
        eventtype: null
      }, { crossdomain: true });
    
      if (res && res.status === 200) {
        setListings(res.data);
      } else {
        alert(res.data.message);
      }
    } catch (err) {
      alert('Failed to retrieve events: ', err.message);
    }
  }

  useEffect(() => {
    retrieveListings();
  }, []);

  // 生成坐标数组,注意MongoDB的坐标是[经度, 纬度],Google Maps需要[纬度, 经度]
  const coordinates = listings 
    ? listings.map(listing => ({ 
        lat: listing.location.coordinates[1], 
        lng: listing.location.coordinates[0] 
      })) 
    : [];

  return (
    <Grid container spacing={2}>
      <Grid item xs={6}>
        <Listings listings={listings} setFeaturedPosts={setFeaturedPosts} />
      </Grid>
      <Grid item xs={6}>
        <MapsComponent coordinates={coordinates} />
      </Grid>
    </Grid>
  );
}

步骤3:修改MapsComponent接收props并响应变化

让MapsComponent监听coordinates props的变化,自动更新地图标记:

import React, { useEffect, useState } from 'react';
import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';

const containerStyle = {
  width: '600px',
  height: '600px',
};

const center = {
  lat: 37.7749,
  lng: -112.4194,
};

function MapsComponent({ coordinates }) {
  const [markers, setMarkers] = useState([]);

  useEffect(() => {
    // 当坐标数组更新时重新生成标记
    setMarkers(
      coordinates.map((location, index) => ({
        key: index,
        position: location,
      }))
    );
  }, [coordinates]); // 依赖coordinates,确保数据变化时触发更新

  return (
    <>
      <LoadScript googleMapsApiKey="API-key">
        <GoogleMap mapContainerStyle={containerStyle} center={center} zoom={15}>
          <Marker position={center} />
          {markers.map((marker) => (
            <Marker 
              key={marker.key} 
              position={marker.position} 
            />
          ))}
        </GoogleMap>
      </LoadScript>
    </>
  );
}

export default React.memo(MapsComponent);

关键注意事项

  1. 坐标格式转换:MongoDB存储的坐标是[经度, 纬度],而Google Maps需要{lat: 纬度, lng: 经度},必须调换顺序否则标记位置会错误。
  2. React数据流:通过props传递状态是React的标准做法,能确保状态变化时组件自动重新渲染,避免全局变量带来的不可预测性。
  3. useEffect依赖:在MapsComponent的useEffect中添加coordinates作为依赖,确保坐标数组更新时立即同步地图标记。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:33:12