javascript - 做出反应。如何仅对现有密钥使用 fetch 和 setState 处理 API 响应中缺少的密钥?
问题描述
我正在开发一个使用公共 API 来获取一些数据的 React 项目。问题是我发现很多有趣且绝对非常有价值的 API 可能会丢失一些数据。例如,我正在使用 waqi.info,它从世界各地的站点收集有关空气质量的信息。这里有一个问题——当我发送请求时,我需要响应 JSON 中特定键的值。有些站不收集部分数据,所以我在 JSON 中没有要查找的密钥。结果我得到了我的期望:
Uncaught (in promise) TypeError: Cannot read property 'v' of undefined
我只需要在响应中存在键的情况下更改状态,或者更好地将状态设置为给定值,例如“无数据”。我可以手动检查每个键的“未定义”,但它非常粗糙,我正在寻找更智能和优雅的东西。组件代码(从大多数不必要的东西中删除)在这里:
class Item extends React.Component {
constructor(){
super();
this.state={
dataSourceName: null,
dataSourceDetailsCO: null,
dataSourceDetailsNO2: null,
dataSourceDetailsPM10: null,
dataSourceDetailsPM25: null,
dataSourceDetailsSO2: null,
dataSourceDetailsTemp: null,
dataSourceDetailsWind: null
};
}
fetchStationDetails = () => {
const stationUid = this.props.uid;
const urlStationDetails = 'https://api.waqi.info/feed/@' + stationUid + '/?token=' + apiKey;
fetch(urlStationDetails)
.then(res => res.json())
.then(json => this.setState({
dataSourceName: json.data.attributions[0].name,
dataSourceDetailsCO: json.data.iaqi.co.v,
dataSourceDetailsNO2: json.data.iaqi.no2.v,
dataSourceDetailsPM10: json.data.iaqi.pm10.v,
dataSourceDetailsPM25: json.data.iaqi.pm25.v,
dataSourceDetailsSO2: json.data.iaqi.so2.v,
dataSourceDetailsTemp: json.data.iaqi.t.v,
dataSourceDetailsWind: json.data.iaqi.w.v
}))
}
render(){
const dataSourceName = this.state.dataSourceName;
return (
<li>
<div>
Id: {this.props.uid} Longitude: {this.props.lon} Latitude: {this.props.lat}
</div>
<div>
General Air Quality Index (AQI): {this.props.aqi}
</div>
<div>
<button onClick={this.fetchStationDetails}>Click to get detailed data</button>
</div>
{dataSourceName ? <ItemData
dataSourceName={this.state.dataSourceName}
dataSourceDetailsCO={this.state.dataSourceDetailsCO}
dataSourceDetailsNO2={this.state.dataSourceDetailsNO2}
dataSourceDetailsPM10={this.state.dataSourceDetailsPM10}
dataSourceDetailsPM25={this.state.dataSourceDetailsPM25}
dataSourceDetailsSO2={this.state.dataSourceDetailsSO2}
dataSourceDetailsTemp={this.state.dataSourceDetailsTemp}
dataSourceDetailsWind={this.state.dataSourceDetailsWind}
/> : null }
</li>
)
}
}
先感谢您 :)
解决方案
这是一个常见问题,您需要始终考虑到这一点,您应该尝试做的是解析 JSON 并检查您要查找的节点是否已定义或创建白名单,您的您可以清理并使其更清晰的代码:
whiteList = {
dataSourceName:"co",
dataSourceDetailsNO2:"no2",
dataSourceDetailsPM10:"pm10",
...
...
}
parseData = (data) => {
try{
Object.entries(this.whiteList).forEach(([key, value]) => {
this.setState({
[key]:data.data.iaqi[value].v
})
})
}catch(e){
//handle Errors
}
}
fetchStationDetails = () => {
const {uid} = this.props;
const urlStationDetails = `https://api.waqi.info/feed/@${uid}/?token=${apiKey}`;
fetch(urlStationDetails)
.then(res => res.json())
.then(json => this.parseData(json))
.catch(console.log)
}
推荐阅读
- mysql - AWS RDS MySQL 连接数
- javascript - 使用拼接删除Javascript中字符串数组的中间字符
- matrix - 如果我知道三个点,如何在 3d 空间中找到平面的角
- javascript - 如果我将套接字连接分配给属性,将事件侦听器应用于该属性,然后分配另一个套接字,侦听器是否仍然有效?
- java - 带有两个范围拇指的圆形 Seekbar
- python - Tkinter 有什么方法可以淡出小部件吗?
- reactjs - 架构 x86_64 react-native firebase 的未定义符号
- regex - xml 模式检查因模式匹配而失败
- javascript - 异步 forEach 循环返回一个数组
- r - 如何从 R 中的数据框列表中选择特定值?