× TypeError: Cannot read property ‘map’ of undefined but can console.log the key holding the array – ReactJS with hooks

  function, javascript, json, reactjs

Apologies but i’m bashing my head off a wall with this and none of the other examples i’ve seen on here have helped. I am trying to map the contents of the array held in the data key of a JSON object which is fetched from the weatherbit API. I’m doing this so that I can access the array properties (including the nested weather object) for a weather app I am trying to build in modern React (I am using hooks). I’ve screenshotted the JSON so you can see the API structure.

Uncollapsed

Collapsed

I can see the array in the inspection window of the browser when I console.log(currentWeather.data). Why can I not map this given that my map is pointing to the data key/attribute of the currentWeather object? I keep receiving "cannot read property ‘map’ of undefined’.

I have a component called CurrentWeatherList which is performing the mapping and then passing the mapped array down as props:

import CurrentWeather from './CurrentWeather';

function CurrentWeatherList({currentWeather}){

    // return nothing if there is no current weather object, otherwise...
    if (!currentWeather) return null;

    console.log(currentWeather);
    console.log(currentWeather.data);


    // Map the currentWeather
    const displayCurrentWeather = currentWeather.data.map(weather => {
        return <CurrentWeather
                weather={weather}/>
    })

    return(
        <>
        {displayCurrentWeather}
        </>
    )
}



export default CurrentWeatherList;

Edited:

My container, CurrentWeatherContainer which is performing the fetch from the API is:

import { useState, useEffect } from "react";
import CurrentWeatherList from "../components/CurrentWeatherList";
import LocationAsCityForm from "../components/LocationAsCityForm";

function CurrentWeatherContainer(){

    // Sets state for the current weather object
    // also sets state for the location input by the user from LocationAsCityForm
    const [currentWeather, setCurrentWeather] = useState([]);
    const [location, setLocation] = useState("");

    
    // handles the location submitted by the "as city" form
    // invokes the fetch passing the location to getCurrentWeatherAsCity

    const handleLocationAsCitySubmit = (location) => {
        getCurrentWeatherAsCity(location);
    }

    // This is the fetch which provides currentWeather from the API using the form location input by user
    
    const getCurrentWeatherAsCity = (location) => {
    const url = "https://api.weatherbit.io/v2.0/current?city="+location+"&key=42f951c1eea94e33a68cd790a1f613fb"

    console.log("Url: " + url);
    
    fetch(url)
        .then(res => res.json())
        .then(data => {
            setCurrentWeather(data);
        })

    }

    // Format the user input to the form
    
    const formatInput = (userInput) => {
        const lowerCase = userInput.toLowerCase();
        const formattedString = lowerCase;
        return formattedString;
    }


    return(
        <>
        This is the CurrentWeatherContainer
        <LocationAsCityForm 
        handleLocationAsCitySubmit={handleLocationAsCitySubmit}
        location={location}
        setLocation={setLocation}
        formatInput={formatInput}
        />

        <CurrentWeatherList 
        location={location}
        currentWeather={currentWeather}
        />

        </>
    )


}


export default CurrentWeatherContainer;

And finally the code for the LocationAsCityForm component which takes in the user inputted location to perform the fetch:

import { Form, Input } from 'semantic-ui-react'

function LocationAsCityForm({handleLocationAsCitySubmit, location, setLocation, formatInput}) {

    const handleInput = (event) => {
        const formattedInput = formatInput(event.target.value);
        setLocation(formattedInput);
    }

    const submitIngredients = (event) => {
        event.preventDefault();
        handleLocationAsCitySubmit(location);
    
    }
    return (
        <> 
    
            <Form className="form-box" onSubmit={submitIngredients}>
                             
                    <Form.Field>
                    <label>Enter your location</label>
                    <Input action='Search' placeholder='e.g. Edinburgh, UK...' onChange={handleInput}/>
                    </Form.Field>              
           </Form>

        </>
    );
}

export default LocationAsCityForm;

Source: Ask Javascript Questions

LEAVE A COMMENT