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

React多地点天气卡片渲染问题:数据传递与组件改造咨询

多地点天气展示 + Monday.com集成解决方案

一、重构为多地点天气展示

1. 修改App.js的状态与数据获取逻辑

将单地点状态改为数组结构,支持批量查询多个地点的天气:

import './App.css';
import React, { useEffect, useState } from "react";
import { Dimmer, Loader } from 'semantic-ui-react';
import Weather from './components/weather';

export default function App() {
  // 存储所有地点的天气数据
  const [weatherDataList, setWeatherDataList] = useState([]);
  // 标记是否正在加载
  const [isLoading, setIsLoading] = useState(true);

  // 测试用的地点经纬度列表(后续替换为从Monday.com获取的数据)
  const initialLocations = [
    { lat: 39.9042, lon: 116.4074 }, // 北京
    { lat: 31.2304, lon: 121.4737 }, // 上海
    { lat: 23.1291, lon: 113.2644 }  // 广州
  ];

  useEffect(() => {
    const fetchWeatherForLocations = async () => {
      setIsLoading(true);
      try {
        // 批量请求所有地点的天气数据
        const weatherPromises = initialLocations.map(location =>
          fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${location.lat}&lon=${location.lon}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
            .then(res => res.json())
        );
        const weatherData = await Promise.all(weatherPromises);
        // 过滤掉请求失败的数据
        const validData = weatherData.filter(data => typeof data.main !== 'undefined');
        setWeatherDataList(validData);
      } catch (err) {
        console.error('天气数据获取失败:', err);
      } finally {
        setIsLoading(false);
      }
    };

    fetchWeatherForLocations();
  }, []);

  return (
    <div className="App">
      {isLoading ? (
        <div>
          <Dimmer active>
            <Loader>Loading..</Loader>
          </Dimmer>
        </div>
      ) : (
        <Weather weatherDataList={weatherDataList} />
      )}
    </div>
  );
}

2. 修改Weather组件渲染多卡片

将单卡片组件改为循环渲染多个卡片:

import React from 'react';
import '../styles.css';
import { Card } from 'semantic-ui-react'
import moment from 'moment';

const Weather = ({ weatherDataList }) => (
  <div className="Cards" style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
    {weatherDataList.map((weatherData, index) => (
      <Card key={index} className="card1">
        <Card.Content>
          <Card.Header className="header">Location: {weatherData.name}</Card.Header>
          <p>{moment().format('dddd')}, {moment().format('LL')} {moment().format('HH:mm')}</p>
          <br></br>
          <p>Temperature: {weatherData.main.temp} &deg;C</p>
          <p>Sunrise: {new Date(weatherData.sys.sunrise * 1000).toLocaleTimeString('en-IN')}</p>
          <p>Sunset: {new Date(weatherData.sys.sunset * 1000).toLocaleTimeString('en-IN')}</p>
          <p>Description: {weatherData.weather[0].main}</p>
          <p>Humidity: {weatherData.main.humidity} %</p>
          <br></br>
        </Card.Content>
      </Card>
    ))}
  </div>
);

export default Weather;

二、集成Monday.com与地理编码

1. 从Monday.com获取地点名称

使用Monday.com的GraphQL API获取看板中的地点数据,需先获取API令牌:

// 封装获取Monday.com地点的函数
const fetchLocationsFromMonday = async () => {
  const apiToken = process.env.REACT_APP_MONDAY_API_TOKEN;
  const boardId = 'YOUR_BOARD_ID'; // 替换为你的看板ID

  const query = `
    query {
      boards(ids: ${boardId}) {
        items {
          name
          column_values(ids: ["location"]) { // 替换为存储地点的列ID
            text
          }
        }
      }
    }
  `;

  const response = await fetch('https://api.monday.com/v2', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': apiToken
    },
    body: JSON.stringify({ query })
  });

  const data = await response.json();
  // 提取地点名称列表
  return data.data.boards[0].items.map(item => item.column_values[0].text);
};

2. 地理编码转换(地点→经纬度)

使用免费的Nominatim API将地点名称转为经纬度:

// 封装地理编码函数
const geocodeLocation = async (locationName) => {
  const response = await fetch(`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(locationName)}&format=json&limit=1`);
  const data = await response.json();
  if (data.length > 0) {
    return {
      lat: parseFloat(data[0].lat),
      lon: parseFloat(data[0].lon)
    };
  }
  return null; // 转换失败返回null
};

3. 整合完整流程

将三个步骤串联,替换App.js中原有的initialLocations逻辑:

useEffect(() => {
  const fetchAllData = async () => {
    setIsLoading(true);
    try {
      // 1. 从Monday.com获取地点名称
      const locationNames = await fetchLocationsFromMonday();
      // 2. 批量转成经纬度
      const geocodePromises = locationNames.map(name => geocodeLocation(name));
      const locations = (await Promise.all(geocodePromises)).filter(Boolean);
      // 3. 批量获取天气数据
      const weatherPromises = locations.map(location =>
        fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${location.lat}&lon=${location.lon}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
          .then(res => res.json())
      );
      const weatherData = await Promise.all(weatherPromises);
      const validData = weatherData.filter(data => typeof data.main !== 'undefined');
      setWeatherDataList(validData);
    } catch (err) {
      console.error('数据获取失败:', err);
    } finally {
      setIsLoading(false);
    }
  };

  fetchAllData();
}, []);

注意事项

  • 所有API密钥(天气API、Monday API)需存放在环境变量中,禁止硬编码
  • 完善错误处理:针对地理编码失败、天气API请求失败等情况做兼容,避免程序崩溃
  • 若地点数量较多,需添加请求防抖或分批请求逻辑,避免触发API速率限制
  • Monday.com的列ID需根据看板实际配置替换,可在Monday开发者工具中查看列ID

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:20:31