React与JavaScript中如何存储JSON响应供其他函数使用
问题原因
fetchWeatherForecast是异步函数,直接调用不会立即返回接口响应的JSON对象,只会返回Promise实例。你把Promise直接传入数据解析函数,自然无法读取到weather、main这类实际响应才有的属性,最终拿不到正确结果。
正确实现方案
核心思路
用React内置的useState存储接口返回的JSON数据,在组件挂载、或者需要刷新数据的时机,通过useEffect触发接口请求,请求成功后把响应结果存入状态,所有业务函数统一从状态中读取数据做解析,同时做好加载、错误态的边界处理,避免渲染报错。
第一步:优化fetchData.js的容错逻辑
- 修正原代码中内部变量和函数重名的问题
- 接口请求失败时统一返回
null,方便上层逻辑判断请求状态 - 给所有数据解析函数加可选链和默认值,避免数据为空时访问属性抛出错误
import { weatherAPIConfig } from "../weatherAPIConfig" export async function fetchWeatherForecast(cityName) { const URL = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&units=metric&appid=${weatherAPIConfig.key}` try { const res = await fetch(URL) if (!res.ok) throw new Error("Request failed") return await res.json() } catch (error) { console.log("Could not find given city"); return null } } export function getWeatherDescription(weatherForecastJSON) { return weatherForecastJSON?.weather?.[0]?.description ?? "暂无数据"; } export function getWeatherTemperature(weatherForecastJSON) { return weatherForecastJSON?.main?.temp ?? "暂无数据" } export function getWeatherWindSpeed(weatherForecastJSON) { return weatherForecastJSON?.wind?.speed ?? "暂无数据"; } export function getWeatherHumidity(weatherForecastJSON) { return weatherForecastJSON?.main?.humidity ?? "暂无数据" }
第二步:改造Row组件,用状态存储响应数据
- 新增三个状态:
weatherData存接口返回的完整JSON、loading标记加载状态、error存储错误信息 - 组件首次挂载时触发数据拉取,请求完成后把结果存入
weatherData - 按加载中、加载失败、正常展示的顺序做条件渲染,数据正常时再调用解析函数从
weatherData中取值渲染
import React, { useState, useEffect } from 'react' import {getWeatherDescription, getWeatherHumidity, getWeatherTemperature, getWeatherWindSpeed, fetchWeatherForecast} from '../../functions/fetchData' import { weatherAPIConfig } from '../../weatherAPIConfig'; function Row() { // 存储接口返回的完整JSON数据,初始值为null const [weatherData, setWeatherData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState("") // 组件挂载时拉取数据 useEffect(() => { const loadWeatherData = async () => { setLoading(true) setError("") const res = await fetchWeatherForecast("London") if (!res) { setError("无法获取对应城市天气数据") } else { setWeatherData(res) } setLoading(false) } loadWeatherData() }, []) if (loading) return <div>数据加载中...</div> if (error) return <div>{error}</div> return ( <div> <div>API-key: {weatherAPIConfig.key}</div> <div>天气描述: {getWeatherDescription(weatherData)}</div> <div>温度: {getWeatherTemperature(weatherData)}℃</div> <div>风速: {getWeatherWindSpeed(weatherData)}m/s</div> <div>湿度: {getWeatherHumidity(weatherData)}%</div> </div> ) } export default Row;
后续如果要在其他业务函数里使用这份天气数据,直接读取weatherData状态传入对应解析函数即可,不需要重复发起接口请求。如果需要切换查询城市,只需要重新调用fetchWeatherForecast传入新城市名,拿到结果后调用setWeatherData更新状态,所有引用该状态的视图都会自动同步更新。
内容的提问来源于stack exchange,提问作者Suleyman Selcuk
相关产品推荐
相关产品推荐

