反应。如何仅对现有键使用 fetch 和 setState 来处理 API 响应中丢失的键?

React. How to deal with missing keys in API response using fetch and setState only for existing keys?

我正在开发一个使用 public API 来获取一些数据的 React 项目。问题是我发现很多有趣且非常有价值的 API 可能会丢失一些数据。例如,我正在使用 waqi.info 从世界各地的站点收集有关空气质量的信息。这是一个问题 - 当我发送请求时,我需要来自特定键的值作为响应 JSON。有些站不收集部分数据,所以JSON中没有我要找的key。结果我得到了我所期望的:

Uncaught (in promise) TypeError: Cannot read property 'v' of undefined

我只需要在响应中存在键的情况下更改状态,或者更好 - 将状态设置为给定值,例如 'No data'。 我可以手动检查 '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)
}