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} °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
相关产品推荐
相关产品推荐

