我对 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调用没有问题,我已经检查了很多次。
答案 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
调用)。我还没有完全测试过这种方法,但我怀疑这个事件顺序是什么给你带来了问题。此外,可能值得考虑添加对有效城市输入的检查,或者甚至可能将输入转换为有效城市的下拉列表以帮助数据完整性。否则,我可以预见拼写错误的城市等会导致问题。