【问题标题】:TypeError: Cannot read properties of undefined (reading 'map') React JSTypeError:无法读取未定义的属性(读取“地图”)React JS
【发布时间】:2021-09-29 04:17:10
【问题描述】:

我遇到了错误TypeError: Cannot read properties of undefined (reading 'map')

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

代码:

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;

【问题讨论】:

  • 您将this.state.weather 更新为parsedData.weather 的值是多少?是数组吗?
  • 是的,这将存储我从 api 获取的所有天气详细信息的数组
  • 请告诉我们parsedData的值。据我所知,this.state.weather 是在初始渲染上定义的数组,因此在您获取数据并更新状态后,this.state.weather 不再定义。这就是您无法读取.map.length 并引发错误的原因。如果我有你的 this.props.api 值,我会自己复制它,看看响应值是什么。

标签: javascript reactjs


【解决方案1】:

问题:

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

解决方案:

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

  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 ...
     )
    }
  }
}

最后:

虽然上面的 sn-p 可以正常工作,但您可以通过同时检查两个 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 与一个空数组。

【讨论】:

    【解决方案2】:

    让我们假设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>
            </>
        );
    }
    

    【讨论】:

    • 感谢您的回答,但它引发了一个错误 => TypeError: Cannot read properties of undefined (reading 'length') ;
    • 是的,我知道,但我的意思是这个过程是异步的。所以这就是为什么值是未定义的
    • 如何解决这个问题??
    • 你必须等待异步进程,直到你得到值。然后你就可以渲染元素了
    猜你喜欢
    • 2021-01-06
    • 2017-11-25
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2017-03-26
    相关资源
    最近更新 更多