代码之家  ›  专栏  ›  技术社区  ›  pierogi01

无法读取未定义的属性(读取“0”)-API问题

  •  0
  • pierogi01  · 技术社区  · 2 年前

    我从来没有想过我必须提出自己的问题,但我来了。我是React的新手。 我在从API获取特定数据时遇到问题。其他也可以,但有

    src={ https://openweathermap.org/img/wn/${cityData?.wweather[0]?.icon}@2x.png }

    我得到错误“无法读取未定义的属性(读取“0”)

    以下是完整代码:

    import React, { useEffect, useState } from "react"
    import { Outlet } from "react-router-dom"
    import sun from '../assets/sun.png'
    
    export default function Weathertab(props){
        
        const [cityData, setCityData] = useState({})
        const apiKey = "b708966eb167246df9118941d4bddc31"
        const cityWeatherData = `https://api.openweathermap.org/data/2.5/weather?q=${props.city}&units=Metric&appid=${apiKey}`
    
        useEffect(function(){
            async function fetchData(){
                await fetch(cityWeatherData)
                    .then(res=> res.json())
                    .then(data => setCityData(data))
            }
            fetchData()
        }, [])
    
        console.log(cityData)
        console.log(props.city)
        return(
            <div className="weather--tab">
                <img className="weather--icon" 
                        src={`https://openweathermap.org/img/wn/${cityData?.weather[0]?.icon}@2x.png`}
                        alt="sun behind a cloud" />
                <h1 className="weather--tab--degrees">{Math.floor(cityData?.main?.temp)}°C</h1>
                <h3 className="weather--tab--city">{props.city}</h3>
                <div className="weather--min--max--temp">
                    <div className="weather--block">
                        <label>Min Temp</label>
                        <p className="weather--min--max" id="weather--min">{Math.floor(cityData?.main?.temp_min)}°C</p>
                    </div>
                    <div className="weather--block">
                        <label>Max Temp</label>
                        <p className="weather--min--max" id="weather--max">{Math.floor(cityData?.main?.temp_max)}°C</p>  
                    </div>
                </div>
                <Outlet />
            </div>
        )
    }
    
    

    我试着用谷歌搜索这个问题(当然也是),但没有任何帮助。问题只出在cityData.wweather[0].icon上

    我试着在useEffect函数中将useState和TheIcon设置为cityData.wweather[0].icon,但没有成功。

    为什么它可以与cityData配合使用?。主要的temp,但不适用于cityData?。天气[0]?。偶像

    2 回复  |  直到 2 年前
        1
  •  0
  •   Meenal Aggarwal    2 年前

    您在cityData中看到问题的原因是什么?。天气[0]?。图标可能是因为cityData最初是一个空对象{}。组件首次渲染时cityData.weather未定义的原因是检索天气数据的API调用仍处于挂起状态。访问未知值上的[0]将导致错误。

    获取数据后,可以有条件地渲染天气图标以解决此问题。在访问其任何元素之前,您可以使用&&操作员查看cityData.weather是否存在。以下是更改代码的方法:

    import React, { useEffect, useState } from "react"
    import { Outlet } from "react-router-dom"
    import sun from '../assets/sun.png'
    
    export default function Weathertab(props){
        
        const [cityData, setCityData] = useState({})
        const apiKey = "b708966eb167246df9118941d4bddc31"
        const cityWeatherData = `https://api.openweathermap.org/data/2.5/weather?q=${props.city}&units=Metric&appid=${apiKey}`
    
        useEffect(function(){
            async function fetchData(){
                await fetch(cityWeatherData)
                    .then(res=> res.json())
                    .then(data => setCityData(data))
            }
            fetchData()
        }, [])
    
        console.log(cityData)
        console.log(props.city)
        return(
            <div className="weather--tab">
                {cityData.weather && (
                    <img className="weather--icon" 
                        src={`https://openweathermap.org/img/wn/${cityData.weather[0].icon}@2x.png`}
                        alt="sun behind a cloud" />
                )}
                <h1 className="weather--tab--degrees">{Math.floor(cityData?.main?.temp)}°C</h1>
                <h3 className="weather--tab--city">{props.city}</h3>
                <div className="weather--min--max--temp">
                    <div className="weather--block">
                        <label>Min Temp</label>
                        <p className="weather--min--max" id="weather--min">{Math.floor(cityData?.main?.temp_min)}°C</p>
                    </div>
                    <div className="weather--block">
                        <label>Max Temp</label>
                        <p className="weather--min--max" id="weather--max">{Math.floor(cityData?.main?.temp_max)}°C</p>  
                    </div>
                </div>
                <Outlet />
            </div>
        )
    }

    通过在标记周围添加{cityData.weather&&(…)},可以确保只有当cityData.weather为true时才会呈现图标,从而避免“无法读取未定义的属性”错误。

        2
  •  0
  •   Saurabh Rana    2 年前

    发生错误是因为您试图使用src加载图像,但最初是您的 cityData?.weather[0]?.icon 为null

    所以当其他字段显示NaN时,这一行呈现错误

    src={`https://openweathermap.org/img/wn/${cityData?.weather[0]?.icon}@2x.png`}
    

    use可以尝试使用状态变量,如使用useState加载,它将在加载数据时显示加载

    这是用于添加加载状态的片段

      const [loading, setLoading] = useState(true);
    useEffect(function () {
        async function fetchData() {
          await fetch(cityWeatherData)
            .then((res) => res.json())
            .then((data) => {
              setCityData(data);
              setLoading(false);
            });
        }
        fetchData();
      }, []);
    
      if (loading) {
        return "loading data";
      }
    

    这是正确的代码

    import React, { useEffect, useState } from "react";
    import { Outlet } from "react-router-dom";
    // import sun from "../assets/sun.png";
    
    export default function Weathertab(props) {
      const [cityData, setCityData] = useState({});
      const [loading, setLoading] = useState(true);
      const apiKey = "b708966eb167246df9118941d4bddc31";
      const cityWeatherData = `https://api.openweathermap.org/data/2.5/weather?q=${props.city}&units=Metric&appid=${apiKey}`;
    
      useEffect(function () {
        async function fetchData() {
          await fetch(cityWeatherData)
            .then((res) => res.json())
            .then((data) => {
              setCityData(data);
              setLoading(false);
            });
        }
        fetchData();
      }, []);
    
      if (loading) {
        return "loading data";
      }
    
      //   console.log(cityData.weather[0]);
      return (
        <div className="weather--tab">
          <img
            className="weather--icon"
            src={`https://openweathermap.org/img/wn/${cityData?.weather[0]?.icon}@2x.png`}
            alt="sun behind a cloud"
          />
          <h1 className="weather--tab--degrees">
            {Math.floor(cityData?.main?.temp)}°C
          </h1>
          <h3 className="weather--tab--city">{props.city}</h3>
          <div className="weather--min--max--temp">
            <div className="weather--block">
              <label>Min Temp</label>
              <p className="weather--min--max" id="weather--min">
                {Math.floor(cityData?.main?.temp_min)}°C
              </p>
            </div>
            <div className="weather--block">
              <label>Max Temp</label>
              <p className="weather--min--max" id="weather--max">
                {Math.floor(cityData?.main?.temp_max)}°C
              </p>
            </div>
          </div>
          <Outlet />
        </div>
      );
    }