开发者问题收集

TypeError:无法读取未定义的属性(读取‘map’)React JS

2021-09-29
17814

我遇到了错误 TypeError: 无法读取未定义的属性(读取“地图”)

此代码应返回卡片标题中的城市名称,该名称已在我的其他文件中定义,但引发了错误。

代码:

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

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

  async componentDidMount() {
    const url = `http://api.weatherapi.com/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;
3个回答

问题:

在 API 调用之前,您的 weather 数组为空,因此使用 this.state.weather.map 将导致错误。

解决方案:

在将 map arrays 一起使用之前,有两件重要的事情:

  1. 检查数组的 定义 (数组是否已定义且存在?)
  2. 检查其 长度 (数组是否有内容?)

首先

通过简单的 if 语句检查其声明/定义:

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

或者使用 ? 简写 if

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

第二步

检查数组的内容,并在检查其 长度 后使用 map 函数(它告诉您数据已从 API 调用等到达并准备好处理)

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

最后:

虽然上述代码片段正常工作,但您可以通过同时检查两个 if 条件来简化它:

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

因此,只需在 Weather 组件的返回中做一些更改:

<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>

可选:

在实际示例中,您可能需要在数据加载时显示一些加载组件正在获取。

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

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

if(anEmptyArray) 的比较结果始终为 true ,且数组为空。

nima
2021-10-16

最简单的方法就是在 map 方法前添加“this.state.weather &&”,首先它会确保“this.state.weather”被定义,然后运行代码,示例如下

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

我们假设 parsedData.weather 具有正确的数据类型。您应该制定条件逻辑,以检查 this.state.weather 是否应具有来自 API 的值。

以下是示例

 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>
        </>
    );
}
Mochamad Faishal Amir
2021-09-29