I'm new to react, have seen some similar issues but haven't found why this is happening. I am getting "Uncaught TypeError: this.state.data.map is not a function". Here is the code. Please help find what the problem is.
import React from "react";
class Forecast extends React.Component {
render() {
const forecastItems = this.props.forecast.map((f) => {
const url = `http://openweathermap.org/img/wn/${f.wather[0].img}@2x.png`;
let ampm = 'AM';
let hour = new Date(f.dt * 1000).getHours();
if (hour > 12) {
hour = hour - 12;
ampm = 'PM';
}
return (
<div className="forecast-item">
<p className="forecast-item__hour">{hour}:00 {ampm}</p>
<p className="forecast-item__temp">{f.temp}</p>
<img src={url} alt={f.weather[0].description}/>
<p className="forecast-item__description">{f.wather[0].main}</p>
</div>
);
});
return (
<div className="forecast">
{forecastItems}
</div>);
}
}
export default Forecast;
Here is the parent companet, where I use my code to get the weather api, it seems to be doing everything right.
import React from "react";
import './App.css';
import SearchMenu from "./Components/search-menu/search-menu";
import CurrentWeather from "./Components/current-weather/current-weather";
import Forecast from "./Components/forecast-weather/forecast-weather";
import {getCurrentWather, getForecast} from './Components/api/weather.api';
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
location: "",
temp: "",
feelsLike: "",
description: "",
img: "",
hourlyForecast: ""
};
}
onInputChange(e) {
this.setState({
location: e.target.value
});
}
async onFormSubmit() {
const weatherRes = await getCurrentWather(this.state.location);
const lat = weatherRes.data.coord.lat;
const lon = weatherRes.data.coord.lon;
const forecastRes = await getForecast (lat,lon);
this.setState({
temp: weatherRes.data.main.temp,
feelsLike: weatherRes.data.main.feels_like,
description: weatherRes.data.weather[0].main,
img: weatherRes.data.weather[0].img,
hourlyForecast: forecastRes.data.hourly
});
}
render() {
return (
<div className="App">
<header className="App-header">
<SearchMenu
location={this.state.location}
inputChange={(e) => this.onInputChange(e)}
formSubmitted={() => this.onFormSubmit()}
/>
<CurrentWeather
currentTemperature={this.state.temp}
feelsLike={this.state.feelsLike}
description={this.state.description}
img={this.state.img}
/>
<Forecast forecast={this.state.hourlyForecast} />
</header>
</div>
);
}
}
export default App;
CodePudding user response:
In the constructor initialize your state like below
...
this.state = {
location: "",
temp: "",
feelsLike: "",
description: "",
img: "",
hourlyForecast: []
};
What is different is that hourlyForecast is now an empty array and not an empty string.
CodePudding user response:
You set state for hourlyForecast
in parent component with string initial value and is not array of data. You should set state like below:
this.state = {
...
hourlyForecast: []
};
CodePudding user response:
I think it should be something like this below, I guess you are passing hourlyForecast as a string which array map function don't understand and throws type error.
import React from "react";
import './App.css';
import SearchMenu from "./Components/search-menu/search-menu";
import CurrentWeather from "./Components/current-weather/current-weather";
import Forecast from "./Components/forecast-weather/forecast-weather";
import {getCurrentWather, getForecast} from './Components/api/weather.api';
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
location: "",
temp: "",
feelsLike: "",
description: "",
img: "",
hourlyForecast: []
};
}
onInputChange(e) {
this.setState({
location: e.target.value
});
}
async onFormSubmit() {
const weatherRes = await getCurrentWather(this.state.location);
const lat = weatherRes.data.coord.lat;
const lon = weatherRes.data.coord.lon;
const forecastRes = await getForecast (lat,lon);
this.setState({
temp: weatherRes.data.main.temp,
feelsLike: weatherRes.data.main.feels_like,
description: weatherRes.data.weather[0].main,
img: weatherRes.data.weather[0].img,
hourlyForecast: Array.isArray(forecastRes.data.hourly) ? forecastRes.data.hourly : [forecastRes.data.hourly]
});
}
render() {
return (
<div className="App">
<header className="App-header">
<SearchMenu
location={this.state.location}
inputChange={(e) => this.onInputChange(e)}
formSubmitted={() => this.onFormSubmit()}
/>
<CurrentWeather
currentTemperature={this.state.temp}
feelsLike={this.state.feelsLike}
description={this.state.description}
img={this.state.img}
/>
<Forecast forecast={this.state.hourlyForecast} />
</header>
</div>
);
}
}
export default App;