admin管理员组

文章数量:1287651

I am facing the error TypeError: Cannot read properties of undefined (reading 'map')

This code should return the name of the city in a card title which is defined in my other file but throwing an error.

Codes:

import React, {Component} from 'react';
import Body from './Body';

class Weather extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weather: [],
    };
  }

  async ponentDidMount() {
    const url = `.json?key=${this.props.api}&q=Jaipur&aqi=no`;
    let data = await fetch(url);
    let parsedData = await data.json();
    this.setState({
      weather: parsedData.weather,
    });
  }

  render() {
    return (
      <div className="container">
        <div className="row">
          {this.state.weather.map((element) => {
            return (
              <div className="col-md-4">
                <Body city={element.location.name} />
              </div>
            );
          })}
        </div>
      </div>
    );
  }
}

export default Weather;

I am facing the error TypeError: Cannot read properties of undefined (reading 'map')

This code should return the name of the city in a card title which is defined in my other file but throwing an error.

Codes:

import React, {Component} from 'react';
import Body from './Body';

class Weather extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weather: [],
    };
  }

  async ponentDidMount() {
    const url = `http://api.weatherapi./v1/current.json?key=${this.props.api}&q=Jaipur&aqi=no`;
    let data = await fetch(url);
    let parsedData = await data.json();
    this.setState({
      weather: parsedData.weather,
    });
  }

  render() {
    return (
      <div className="container">
        <div className="row">
          {this.state.weather.map((element) => {
            return (
              <div className="col-md-4">
                <Body city={element.location.name} />
              </div>
            );
          })}
        </div>
      </div>
    );
  }
}

export default Weather;
Share Improve this question edited Oct 16, 2021 at 12:28 nima 8,92512 gold badges40 silver badges55 bronze badges asked Sep 29, 2021 at 4:17 Yatharth SinghYatharth Singh 291 gold badge1 silver badge3 bronze badges 3
  • What is the value of parsedData.weather that you are updating this.state.weather to? Is it an array? – Drew Reese Commented Sep 29, 2021 at 4:41
  • yes this will store an array of all my weather details fetched from the api – Yatharth Singh Commented Oct 1, 2021 at 5:40
  • Please show us the value of parsedData. From what I can tell, this.state.weather is a defined array on the initial render, so somehow after you fetch data and update state, this.state.weather is no longer defined. This is why you can't read .map or .length and an error is thrown. If I had your this.props.api value I'd just reproduce this myself and see what the response value is. – Drew Reese Commented Oct 1, 2021 at 16:13
Add a ment  | 

3 Answers 3

Reset to default 6

The Problem:

your weather array is empty before the API call so using this.state.weather.map will cause the error.

The Solution:

There are two important things before using the map with arrayes:

  1. check for the definition of the array (is the array defined and exists?)
  2. check its length (is the array has some content?)

First

check its declaration/definition by a simple if statement:

{
  if(myArrayOfData) {
    myArrayOfData.map(
      // rest of the codes ...
    )
  }
}

Or with using ? shorthanded of if

{
  myArrayOfData?.map(
    // rest of the codes ...
  )
}

Second

check for the contents of the array and use the map function after checking its length (which tells you the data has arrived from the API call etc. and is ready to process)

{
  if(myArrayOfData) {
    if(myArrayOfData.length > 0) {
     myArrayOfData.map(
        // rest of the codes ...
     )
    }
  }
}

Finally:

while the above snippet works properly, you can simplify it by checking both if conditions together:

{
  if(myArrayOfData?.length > 0) {
     myArrayOfData.map(
        // rest of the codes ...
     )
  }
}

So, simply make some changes in the return of Weather ponent:

<div className="row">
  {
    if(this.state.weather?.length > 0) {
      this.state.weather.map((element) => {
        return (
          <div className="col-md-4" key={element.id}>  // also don't forget about the passing a unique value as key property
            <Body city={element.location.name}/>
          </div>
        );
      })
    }
  }
</div>

Optional:

In real-world examples, you may need to show some loading ponents while the data is fetching.

{
  if(myArrayOfData?.length > 0) {
    myArrayOfData.map(
      // rest of the codes ...
    )
  } else {
    <Loading />
  }
}
Be Aware
const anEmptyArray  = []

if(anEmptyArray){
  // rest of the codes ...
}

The result of parison on if(anEmptyArray) is always true with an empty array.

the simplest way is just to add "this.state.weather &&" before map method, first it will make sure that "this.state.weather" is defined and then run the code, example is below

{this.state.weather && this.state.weather.map((element) => {
            return (
              <div className="col-md-4">
                <Body city={element.location.name} />
              </div>
            );
})}

Lets make an assumption that parsedData.weather have correct data type. You should make a conditional logic, to check this.state.weather should have a value from API.

Here's an example

 render() {
    const { weather } = this.state; // Access the state `weather`
    return (
        <>
            <div className="container">
                <div className="row">
                     { /* This way use conditional ternary operator */ }
                    {weather.length ? weather.map((element) => {
                        return (
                            <div className="col-md-4">
                                <Body city={element.location.name}/>
                            </div>
                        );
                    }) : <span>Loading...</span>}
                </div>

            </div>
        </>
    );
}

本文标签: javascriptTypeError Cannot read properties of undefined (reading 39map39) React JSStack Overflow