Home > Back-end >  Uncaught TypeError: this.props.forecast.map is not a function
Uncaught TypeError: this.props.forecast.map is not a function

Time:12-25

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;

enter image description here

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;
  • Related