类型错误:无法读取未定义数据提取的属性“0”

时间:2021-03-12 05:02:05

标签: javascript reactjs web react-fullstack

我对 reactjs 很陌生,我正在做我的第二个关于 Weather Forcast APP 的项目。每当我想获取存储在 weatherList 中的数据时,我都会收到错误消息。如何理解“类型错误:无法读取未定义数据提取的属性‘0’”。

请帮助我提供正确的建议,我应该使用这些建议来避免此错误。

以下是我的 App.js 代码:-

import React, { useEffect, useState} from "react";
import './App.css';
import SearchBar from './components/SearchBar/SearchBar';
import WeatherBox from './components/WeatherCard/WeatherBody';
import { Grid } from "@material-ui/core";

import { makeStyles } from '@material-ui/core/styles';

require('dotenv').config();  


const useStyles = makeStyles({
  root: {
    minWidth: 275,
    backgroundColor: '#091f43',
    color: 'var(--text_light)',
    margin: 'auto'
  },
  inputs: {
      border: 'none',
      background: 'none',
      outline: 'none',
      color: 'inherit',
      fontSize: '2rem',
      height: '40px',
      padding: '5px 5px 10px',
      borderBottom: '1px solid'
  },
  buttons: {
      border: 'none',
      outline: 'none',
      color: 'inherit',
      fontSize: '1rem',
      fontWeight: 'bold',
      letterSpacing: '0.1em',
      padding: '15px 20px',
      marginLeft: '15px',
      borderRadius: '5px',
      backgroundColor: 'red',
      transition: 'background 0.3s ease-in-out',
      cursor:'pointer'
  },
  formStyling: {
      position: 'relative',
      display: 'flex',
      alignItems: 'center',
  },
  headings: {
      fontWeight: 'bold',
      fontSize: '4rem',
      letterSpacing: '0.02em',
      padding: '0 0 30px 0'
  }
});


const API_KEY = process.env.REACT_APP_BART_API_KEY;

function App() {

  const [city, setCity] = useState(null);
  const [responseData, setresponseData] = useState(null);
  const [searches, setSearches] = useState(null);
  const [weatherList, setweatherList] = useState([]);
  const [date, setdate] = useState(null);
  // const [buttonClick, setButtonClick] = useState(false);

  const classes = useStyles();
  const isRowBased = window.matchMedia('(min-width: 700px)');

  useEffect( () => {
    const fetchApi = async () => {
      const url = `https://api.openweathermap.org/data/2.5/forecast?q=${searches}&appid=${API_KEY}`;
      const response = await fetch(url);
      // console.log(response);
      const resJson = await response.json();
      setresponseData(resJson);
      setweatherList(resJson.list);
    };

    fetchApi();
  }, [searches])
  
  function dataExtracting()
  {
    var dates = weatherList[0].dt_txt;
    setdate(dates);
  }
  function handleChange(event) {
    const cityName = event.target.value;
    setCity(cityName);
  }

  function submitCity(event) {
    setSearches(city);

      dataExtracting();
    
    // setButtonClick(true);
    // setTimeout( () => setButtonClick(false), 2000);
    event.preventDefault();
  }

  return (
    <div className="App">
      <Grid className={classes.root} sm={6}>
        <h1 className={classes.headings}>Weather Forcast App</h1>
        <form className={classes.formStyling} style={styles.container(isRowBased)}>
            <input onChange={handleChange} className={classes.inputs} style={styles.containerInput(isRowBased)} type="text" placeholder="Search for a city" autoFocus />
            </form>

            <button className={classes.buttons} style={styles.containerButton(isRowBased)} type="submit" onClick={submitCity}>Search</button>
            <span class="msg"></span>
        
      </Grid>
      <WeatherBox />    
    </div>
  );
}

const styles = {
  container: isRowBased => ({
      flexDirection: 'column',
    width: '100%'
  }),
  containerInput: isRowBased=> ({
      width: '100%'
  }),
  containerButton: isRowBased => ({
      margin: '20px 0 0 0',
      width: '100%'
  })
};

export default App;

这是我收到的错误:-

TypeError: Cannot read property '0' of undefined
dataExtracting
P:/Web Dev/Weather-Application-Reactjs/weatherapp/src/App.js:87
  84 | 
  85 | function dataExtracting()
  86 | {
> 87 |   var dates = weatherList[0].dt_txt;
     | ^  88 |   setdate(dates);
  89 | }
  90 | function handleChange(event) {

编辑

我已经检查了 chrome inspect 中的状态,我看到我想保存在 weatherList 中的数据正在保存,没有任何错误,但我无法通过 dataExtracting() 函数访问它。实际上,我需要从响应中获取列表,然后提取 5 天的天气数据以显示在 Web 应用程序中。为此,我使用了在 submitCity() 函数中调用的 dataExtracting() 函数。仅添加功能后,我收到此错误。这个编辑是为了澄清API调用没有问题,我已经检查了很多次。

3 个答案:

答案 0 :(得分:0)

您能否通过输入控制台 resJson.list 来检查数据是否存在。 你应该试试

var dates = responseData[0].dt_txt;
setdate(dates);

答案 1 :(得分:0)

如果您使用的是 OpenWeatherMap API,请确保您已正确为您的州分配值。如果我们尝试访问 JSON 对象而没有正确解析它们,那么 Node.js 有时会被创建。

 const data = {
  "cod": "200",
  "message": 0,
  "cnt": 40,
  "list": [
    {
      "dt": 1596564000,
      "main": {
        "temp": 293.55,
        "feels_like": 293.13,
        "temp_min": 293.55,
        "temp_max": 294.05,
        "pressure": 1013,
        "sea_level": 1013,
        "grnd_level": 976,
        "humidity": 84,
        "temp_kf": -0.5
      },
      "weather": [
        {
          "id": 500,
          "main": "Rain",
          "description": "light rain",
          "icon": "10d"
        }
      ],
      "clouds": {
        "all": 38
      },
      "wind": {
        "speed": 4.35,
        "deg": 309
      },
      "visibility": 10000,
      "pop": 0.49,
      "rain": {
        "3h": 0.53
      },
      "sys": {
        "pod": "d"
      },
      "dt_txt": "2020-08-04 18:00:00"
    },

  ]};
    


const wetherList = data.list[0].dt_txt;
console.log(wetherList);

//let x = wetherList.dt_txt;
//console.log(x); 
// console.log(wetherList[dt]);

幸运的是,我得到了 dt_list

答案 2 :(得分:0)

我想知道您是否在正确填充列表之前尝试访问该列表。我的意思是你在 useEffect 中的初始 API 调用应该返回一个错误,因为它看起来像这样:

  useEffect( () => {
    const fetchApi = async () => {
      const url = `https://api.openweathermap.org/data/2.5/forecast?q=null&appid=<YOUR_KEY>`;
      const response = await fetch(url);
      // console.log(response);
      const resJson = await response.json();
      setresponseData(resJson);
      setweatherList(resJson.list);
    };

当我使用我的 API 密钥执行此测试时,我的响应是:

{
    "cod": "404",
    "message": "city not found"
}

由于您将城市的初始状态设置为 null,因此第一遍不应提供任何数据,这可以解释为什么您的 weatherList 是 undefined。我唯一的想法是,在您尝试访问 submitCity 函数中的搜索列表之前,您的 setSearches 函数没有完成 fetchApi 并完成 dataExtracting() 调用。由于您需要使用新城市更新状态,然后输入您的异步函数并等待响应,等待转换,然后在输入您的 dataExtracting 函数之前设置所有列表,我相信这可能是问题所在。

几个可能有效的解决方案是:在您的 useEffect 中添加检查以查看是否有列表。如果有,立即提取数据并setdate。我不喜欢这个解决方案,但我认为它应该有效:

  useEffect( () => {
    const fetchApi = async () => {
      const url = `https://api.openweathermap.org/data/2.5/forecast?q=${searches}&appid=5b451f60067d169e5b9acb877efadcda`;
      const response = await fetch(url);
      // console.log(response);
      const resJson = await response.json();
      setresponseData(resJson);
      setweatherList(resJson.list);

      if (resJson.list && resJson.list.length) {
          setdate(resJson.list[0].dt_txt);
      }
    };

如果您在 weatherList 中执行 useEffect 检查,那么您可以将设置搜索和提取 submitCity 中的日期的逻辑分离(如果您确实添加了这个要使用效果,您需要从 dataExtraction 中删除 submitCity 调用)。我还没有完全测试过这种方法,但我怀疑这个事件顺序是什么给你带来了问题。此外,可能值得考虑添加对有效城市输入的检查,或者甚至可能将输入转换为有效城市的下拉列表以帮助数据完整性。否则,我可以预见拼写错误的城市等会导致问题。