React项目中无法读取API返回JSON对象的问题求助
问题:无法在WeatherView组件中读取API返回的JSON数据
我的项目包含三个组件:
- SearchBarComponent:输入API查询值,提交后传递给MainPageComponent
- MainPageComponent:作为组件枢纽,调用API并将响应数据传给WeatherView
- WeatherView:负责展示API返回的JSON数据
现在的问题是,我没办法在WeatherView里读取JSON对象中的数据,不管用props.currentPlace.SOMETHING还是props.currentPlace["SOMETHING"]都无效。
各组件代码
1. SearchBarComponent
const SearchBarComponent = (props: {handleSearch: Function}) => { const [searchVal, setSearchVal] = useState(''); const [dataList, setDataList] = useState<Object>(); const handleSubmitEvent = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); props.handleSearch(searchVal); } const handleSearchingOnChange = (arg: string) =>{ if(arg !== '') { return fetch(`${apiOptions.url}${arg}&limit=10&min_population=100000`, apiOptions) .then(res => res.json()) .then(json => setDataList(Object.keys(json).map((k, i) => <div key={i} className="bg-light"> <p className="font-weight-bold"> {json[i].name} - {json[i].country}</p> </div> ))) .catch(err => console.error('error:' + err)); } } const searchForm = <div className="border-dark d-block m-20"> <form onSubmit={handleSubmitEvent}> <input type="text" value={searchVal} onChange={(e) => setSearchVal(e.target.value)} onInput={() => handleSearchingOnChange(searchVal)} /> <button type="submit" className="btn btn-outline-primary">Szukaj!</button> </form> </div> return ( <> <div className="d-Block"> <> {searchForm} {dataList} </> </div> </> ); } export default SearchBarComponent;
2. MainPageComponent
const MainPageComponent = () => { const [currentLocation, setCurrentLocation] = useState(Object); useEffect(() => { }, [currentLocation]); const handleSearch = (arg: string) => { return fetch(`${weatherApiOptions.url}?key=${weatherApiOptions.key}&q=${arg}&aqi=no`) .then(res => res.json()) .then(json => setCurrentLocation(json)) .catch(err => console.error('error:' + err)); } return ( <div className="d-flex align-items-center justify-content-center"> <SearchBarComponent handleSearch={handleSearch}/> <WeatherView currentPlace={currentLocation}/> </div> ); } export default MainPageComponent;
3. WeatherView组件
const WeatherView = (props: {currentPlace: Object}) => { console.log(props.currentPlace); return ( <div> <p>{props.currentPlace.current} </p> </div> ) } export default WeatherView;
API返回的JSON结构
返回的JSON大致结构如下:
{ "location": { "name": "城市名", "region": "地区", "country": "国家" }, "current": { "temp_c": 20, "temp_f": 68, "condition": { "text": "多云", "icon": "图标链接", "code": 1003 } } }
问题分析与解决方案
核心问题1:初始状态错误
MainPageComponent中currentLocation的初始状态设为了Object构造函数,而非空对象,导致组件首次渲染时props.currentPlace不是API返回的对象:
// 错误写法 const [currentLocation, setCurrentLocation] = useState(Object); // 正确写法 const [currentLocation, setCurrentLocation] = useState<Record<string, any>>({});
核心问题2:未处理异步加载状态
API请求是异步操作,首次渲染时currentLocation为空对象,直接访问属性会报错,需添加空值判断:
修改WeatherView组件:
const WeatherView = (props: {currentPlace: Record<string, any>}) => { const currentWeather = props.currentPlace.current; return ( <div> {currentWeather ? ( <> <p>当前温度:{currentWeather.temp_c}°C</p> <p>天气状况:{currentWeather.condition.text}</p> </> ) : ( <p>请搜索城市查看天气</p> )} </div> ) } export default WeatherView;
额外优化:TypeScript类型定义
为避免类型模糊,建议给API返回数据定义接口:
interface WeatherLocation { name: string; region: string; country: string; } interface WeatherCondition { text: string; icon: string; code: number; } interface CurrentWeather { temp_c: number; condition: WeatherCondition; } interface WeatherResponse { location: WeatherLocation; current: CurrentWeather; } // 组件中使用 const MainPageComponent = () => { const [currentLocation, setCurrentLocation] = useState<WeatherResponse>({} as WeatherResponse); // ... } const WeatherView = (props: {currentPlace: WeatherResponse}) => { // ... }
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

