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

React项目API数据控制台可见但页面不渲染,报weather、wind未定义

问题描述

我已经花了好几个小时尝试解决这个问题,但一直没成功。API返回的数据能在控制台正常显示,但就是没法在浏览器页面上渲染出来,我不确定是不是代码哪里出错了,下面是我的代码,麻烦帮忙排查一下。

import React, { useState, useEffect } from "react";
import "../Componentstyle/Main.css";
export default function Maindata() {
  const [data, setData] = useState(null);

  let weather = async () => {
    const key = "1ab6ef20384db1d7d9d205d609f7eef0";
    await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=dubai&appid=${key}&units=metric&formatted=0`
    )
      .then((response) => response.json())
      .then((actualData)=> setData(actualData));

  };
  useEffect(() => {
    weather()
  }, []);
  const link = `http://openweathermap.org/img/w/${data.weather[0].icon}.png`

  return (
    <div className="maindata">
      <div className="city">{data.name}</div>
      <div className="temp">{data.main.temp} C</div>
      <div className="icon"><img src={link} alt="not found" /> </div>
      <div className="feel">feels Like {data.main.feels_like} C</div>
      <div className="wind">Wind {data.wind.speed} Km/hr</div>
      <div className="cloudy">{data.weather[0].main}</div>
      <div className="humidity">humidity {data.main.humidity}%</div>
      <div className="sunrise">sunrise :- {(new Date((data.sys.sunrise)*1000).toUTCString())} </div>
      <div className="sunset">sunset :- {new Date(data.sys.sunset*1000).toUTCString()}</div>
    </div>
  );
}
问题排查与修复

核心问题

组件初始化时data的初始值是null,第一次渲染时直接访问data.weather[0].icon、data.name等属性会触发Cannot read properties of null的错误,导致组件崩溃无法渲染。而控制台能看到数据是因为后续API请求完成后data被更新,但此时组件已经报错停止渲染了。

修复方案

方案1:添加加载与错误状态判断(推荐)

通过加载状态控制渲染流程,避免在数据未准备好时访问属性,同时增加错误处理:

import React, { useState, useEffect } from "react";
import "../Componentstyle/Main.css";
export default function Maindata() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const weather = async () => {
    try {
      const key = "1ab6ef20384db1d7d9d205d609f7eef0";
      const response = await fetch(
        `https://api.openweathermap.org/data/2.5/weather?q=dubai&appid=${key}&units=metric&formatted=0`
      );
      if (!response.ok) throw new Error('天气数据请求失败');
      const actualData = await response.json();
      setData(actualData);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    weather();
  }, []);

  // 加载中状态
  if (loading) return <div>加载天气数据中...</div>;
  // 错误状态
  if (error) return <div>出错了:{error}</div>;
  // 无数据兜底
  if (!data) return <div>未获取到天气数据</div>;

  const link = `http://openweathermap.org/img/w/${data.weather[0].icon}.png`;

  return (
    <div className="maindata">
      <div className="city">{data.name}</div>
      <div className="temp">{data.main.temp}℃</div>
      <div className="icon"><img src={link} alt="天气图标" /></div>
      <div className="feel">体感温度 {data.main.feels_like}℃</div>
      <div className="wind">风速 {data.wind.speed} Km/hr</div>
      <div className="cloudy">{data.weather[0].main}</div>
      <div className="humidity">湿度 {data.main.humidity}%</div>
      <div className="sunrise">日出时间:{new Date(data.sys.sunrise * 1000).toUTCString()}</div>
      <div className="sunset">日落时间:{new Date(data.sys.sunset * 1000).toUTCString()}</div>
    </div>
  );
}

方案2:使用可选链操作符兜底

如果不想添加加载状态,可以用可选链?.避免访问null属性报错,但这种方式会在数据加载前显示空内容:

// 修改链接生成逻辑
const link = data?.weather?.[0]?.icon ? `http://openweathermap.org/img/w/${data.weather[0].icon}.png` : '';

// 渲染部分的每个属性都添加可选链
return (
  <div className="maindata">
    <div className="city">{data?.name}</div>
    <div className="temp">{data?.main?.temp}℃</div>
    <div className="icon"><img src={link} alt="天气图标" /></div>
    <div className="feel">体感温度 {data?.main?.feels_like}℃</div>
    <div className="wind">风速 {data?.wind?.speed} Km/hr</div>
    <div className="cloudy">{data?.weather?.[0]?.main}</div>
    <div className="humidity">湿度 {data?.main?.humidity}%</div>
    <div className="sunrise">日出时间:{data?.sys?.sunrise ? new Date(data.sys.sunrise * 1000).toUTCString() : ''}</div>
    <div className="sunset">日落时间:{data?.sys?.sunset ? new Date(data.sys.sunset * 1000).toUTCString() : ''}</div>
  </div>
);

额外优化点

  • 移除async/await与then的混用,统一用await写法更清晰易读
  • 添加API请求错误处理,避免请求失败时组件崩溃
  • 中文环境下把温度单位改为℃更符合用户习惯

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:50:51