React Native中如何用switch case调用多API并实现公交时间自动更新?
解决你的React Native公交应用问题
嘿,我来帮你搞定这两个头疼的问题!咱们一步步来,先解决多API调用,再搞定自动更新的事儿~
一、批量调用6个API接口
完全不用纠结switch case!咱们换个更简洁的思路:把所有站点的ID存成数组,写个通用的请求函数,一次性发起所有请求,代码维护起来也方便。
步骤1:整理站点信息,写通用请求函数
先把6个站点的stop ID和对应坐标整理好,再写一个专门请求单站点数据的函数:
// 替换成你实际的6个站点ID const STOP_IDS = [ "01000053207", "010000xxxx1", "010000xxxx2", "010000xxxx3", "010000xxxx4", "010000xxxx5" ]; // 每个站点对应的坐标,替换成实际位置 const STOP_COORDINATES = { "01000053207": { latitude: 77.232, longitude: -44.292 }, "010000xxxx1": { latitude: xxx, longitude: xxx }, // 补充其他站点坐标 }; // 通用请求函数:传入站点ID,返回整理好的发车信息 fetchBusData = async (stopId) => { const url = `https://transportapi.com/v3/uk/bus/stop/${stopId}/live.json?app_id=d7180b02&app_key=47b460aac35e55efa666a99f713cff28&group=route&nextbuses=yes`; try { const response = await fetch(url); const responseJson = await response.json(); // 提取线路和发车时间,整理成字符串 const departures = []; for (const route in responseJson.departures) { const bus = responseJson.departures[route][0]; departures.push(`${bus.line}: ${bus.aimed_departure_time}`); } return { stopId, departures: departures.join(' ') }; } catch (error) { console.error(`站点${stopId}数据加载失败:`, error); return { stopId, departures: "暂无数据" }; } };
步骤2:批量发起所有请求
用Promise.all并行请求所有站点,效率更高,然后把结果存到state里:
componentDidMount() { this.fetchAllBuses(); // 先埋个定时器的位置,后面讲自动更新 } fetchAllBuses = async () => { // 生成所有请求的Promise数组 const fetchPromises = STOP_IDS.map(stopId => this.fetchBusData(stopId)); // 等待所有请求完成 const allBusData = await Promise.all(fetchPromises); // 把结果转成「站点ID: 发车信息」的映射,方便渲染 this.setState({ busData: allBusData.reduce((acc, item) => { acc[item.stopId] = item.departures; return acc; }, {}) }); };
步骤3:渲染多个Marker
现在可以循环渲染所有站点的Marker了,直接关联站点ID对应的坐标和数据:
render() { return ( <MapView style={{ flex: 1 }}> {STOP_IDS.map(stopId => ( <MapView.Marker key={stopId} coordinate={STOP_COORDINATES[stopId]} title={`公交站点`} // 可以改成实际站点名称 description={this.state.busData?.[stopId] || "加载中..."} image={require('./bus.png')} /> ))} </MapView> ); }
二、实现公交时间自动更新
要解决时间不刷新的问题,咱们用定时器定时重新拉取数据就行,比如每分钟刷新一次(你可以根据需求调整间隔)。
步骤1:添加定时器和清理逻辑
在组件里维护定时器ID,组件挂载时启动,卸载时清理,避免内存泄漏:
constructor(props) { super(props); this.state = { busData: {} }; this.updateTimer = null; // 保存定时器ID,方便后续清理 } componentDidMount() { this.fetchAllBuses(); // 每分钟刷新一次(60000毫秒) this.updateTimer = setInterval(() => { this.fetchAllBuses(); }, 60000); } componentWillUnmount() { // 组件卸载时一定要清除定时器! if (this.updateTimer) { clearInterval(this.updateTimer); } }
小提醒:修正你原代码的setState错误
你原来的setState写法有问题:直接this.state.name.push()再setState不会触发组件重新渲染,因为数组是引用类型。正确的做法是创建新数组,比如:
// 错误写法 this.setState({ state : this.state["name"].push(...) }); // 正确写法 this.setState(prevState => ({ name: [...prevState.name, newItem], name1: [...prevState.name1, line, ": ", time, " "] }));
不过咱们上面的批量请求代码已经用了更合理的处理方式,就不用再这么写啦~
完整代码示例
把上面的内容整合起来,完整的组件大概是这样:
import React from 'react'; import MapView, { Marker } from 'react-native-maps'; const STOP_IDS = [ "01000053207", "010000xxxx1", "010000xxxx2", "010000xxxx3", "010000xxxx4", "010000xxxx5" ]; const STOP_COORDINATES = { "01000053207": { latitude: 77.232, longitude: -44.292 }, "010000xxxx1": { latitude: xxx, longitude: xxx }, // 补充其他站点坐标 }; export default class App extends React.Component { constructor(props) { super(props); this.state = { busData: {} }; this.updateTimer = null; } componentDidMount() { this.fetchAllBuses(); // 每分钟刷新一次数据 this.updateTimer = setInterval(() => this.fetchAllBuses(), 60000); } componentWillUnmount() { if (this.updateTimer) clearInterval(this.updateTimer); } fetchBusData = async (stopId) => { const url = `https://transportapi.com/v3/uk/bus/stop/${stopId}/live.json?app_id=d7180b02&app_key=47b460aac35e55efa666a99f713cff28&group=route&nextbuses=yes`; try { const response = await fetch(url); const responseJson = await response.json(); const departures = []; for (const route in responseJson.departures) { const bus = responseJson.departures[route][0]; departures.push(`${bus.line}: ${bus.aimed_departure_time}`); } return { stopId, departures: departures.join(' ') }; } catch (error) { console.error(`站点${stopId}数据加载失败:`, error); return { stopId, departures: "暂无数据" }; } }; fetchAllBuses = async () => { const fetchPromises = STOP_IDS.map(id => this.fetchBusData(id)); const allData = await Promise.all(fetchPromises); this.setState({ busData: allData.reduce((acc, item) => { acc[item.stopId] = item.departures; return acc; }, {}) }); }; render() { return ( <MapView style={{ flex: 1 }}> {STOP_IDS.map(stopId => ( <Marker key={stopId} coordinate={STOP_COORDINATES[stopId]} title={`公交站点`} description={this.state.busData[stopId] || "加载中..."} image={require('./bus.png')} /> ))} </MapView> ); } }
内容的提问来源于stack exchange,提问作者user7503333
相关产品推荐
相关产品推荐

