You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:24:56