You need to enable JavaScript to run this app. React通过props传递数据设置为state后出现undefined报错如何解决?
优惠活动
大模型
产品
解决方案
定价
更多

React通过props传递数据设置为state后出现undefined报错如何解决?

问题根因
  • 接口请求为异步操作,父组件data初始值是空数组,首次渲染时data[0]为undefined,传入子组件后直接访问weather.temp就会触发属性读取报错
  • ActiveWeather组件内部冗余维护了weather状态,需要通过useEffect同步props,增加了时序问题风险,同时父组件传入的activeWeather参数完全未被使用,导致点击侧边栏切换城市的逻辑失效
  • 父组件activeWeather初始值设为空数组,和后续存储单个天气对象的类型不匹配,存在隐式类型问题
修复方案

1. 父组件App修改

const fetchCity = async (city) => {
    const res = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`);
    return {
        description: res.data.weather[0].description,
        icon: res.data.weather[0].icon,
        temp: res.data.main.temp,
        city: res.data.name,
        country: res.data.sys.country,
        id: res.data.id,
    };
};

function App() {
    const [data, setData] = useState([]);
    // 初始值改为null,匹配单个对象类型
    const [activeWeather, setActiveWeather] = useState(null);

    useEffect(() => {
        const fetchCities = async () => {
            const citiesData = await Promise.all(["Ottawa", "Toronto", "Vancouver", "California", "London"].map(fetchCity)).catch((err) => {
                console.log(err);
            });
            setData(citiesData || []);
            // 请求完成后默认选中第一个城市
            if(citiesData?.length) setActiveWeather(citiesData[0])
        };
        fetchCities();
    }, []);

    const handleClick = (event) => {
        const weather = JSON.parse(event.target.dataset.value);
        setActiveWeather(weather);
    };

    return (
        <div className="App">
            <Header />
            <Container>
                <Row>
                    <Col>
                        <WeatherPanel data={data} handleClick={handleClick} />
                    </Col>
                    <Col>
                        {/* 直接传activeWeather即可,不需要再传data[0] */}
                        <ActiveWeather activeWeather={activeWeather} />
                    </Col>
                </Row>
            </Container>
        </div>
    );
}

export default App;

2. 子组件ActiveWeather修改

去掉冗余的内部状态,直接用props传入的activeWeather,渲染前做空值判断:

import React from "react";
import { Container, Card } from "react-bootstrap";

const ActiveWeather = ({activeWeather}) => {
    // 空值时显示加载提示
    if(!activeWeather) return <Container><Card><Card.Header>加载中...</Card.Header></Card></Container>

    return (
        <Container>
            <Card>
                <Card.Header>{activeWeather.city}, {activeWeather.country}</Card.Header>
                <Card.Body>
                    <img src={`http://openweathermap.org/img/wn/${activeWeather.icon}@2x.png`} alt="天气图标" />
                    <p>温度:{activeWeather.temp}</p>
                    <p>天气:{activeWeather.description}</p>
                </Card.Body>
            </Card>
        </Container>
    );
};

export default ActiveWeather;

3. 子组件WeatherPanel可选优化

原代码里ListGroup.Item嵌套了一层多余的ListGroup.Item,调整结构避免渲染异常:

const WeatherPanel = (props) => {
    return (
        <div>
            <Container fluid>
                <Card style={{ boxShadow: "0  0  10px 2px lightgrey" }}>
                    <Card.Header> 常用地点</Card.Header>
                    <ListGroup variant="flush">
                        {props.data.map((item) => (
                            <ListGroup.Item key={item.id} data-value={JSON.stringify(item)} onClick={props.handleClick}>
                                <img src={`http://openweathermap.org/img/wn/${item.icon}@2x.png`} alt="天气图标" />
                                {item.city + ", " + item.country}
                            </ListGroup.Item>
                        ))}
                    </ListGroup>
                </Card>
            </Container>
        </div>
    );
};

export default WeatherPanel;

内容的提问来源于stack exchange,提问作者zer0day

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 22:06:03