【问题标题】:"TypeError: Cannot read property 'map' of undefined" but can console log result completely fine?“TypeError:无法读取未定义的属性'map'”但控制台日志结果可以完全正常吗?
【发布时间】:2021-03-11 20:27:32
【问题描述】:

我目前有两种状态。一个是一个空数组,叫做“subproducts”,另一个叫做“additionalprod”。

subproducts 是一个数组,它使用 Axios 从我的后端数据库中提取信息。它安装在 componentDidMount 内部以供 API 调用。

additionalprod(uct) 是一个状态,它从父级的道具中获取其值,它是一个数字,在这种情况下,出于我的测试目的,数字是 5。数字 5 链接到一个包含 3 的小数组特性。产品、img_url 和 id。

当我控制台记录确切的代码时

console.log(this.state.subproducts[5])

我得到了我想要的响应,那个特定的数组,所以我 100% 正确地定位它。它目前有 2 个数组,里面有自己的道具。

但是,当我尝试通过该状态映射时,使用代码

{this.state.subproducts[5].map((product) => {
<h1>{product.img_url}</h1>
})}

我得到了错误

TypeError: Cannot read property 'map' of undefined

有人知道怎么回事吗?

有问题的代码:

import React from "react"
import axios from "axios"

class SubProducts extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      subproducts: [],
      stage: "3",
      selected: this.props.selected,
      additionalprod: this.props.additionalprod,
    }
  }

  componentDidMount() {
    axios.get("http://localhost/api/subproducts.php").then((res) => {
      this.setState({ subproducts: res.data })
      console.log(this.state.subproducts[5])
    })
  }

  render() {
    return (
      <div>
        {this.state.subproducts[this.state.additionalprod].map((product) => {
          ;<h1>{product.img_url}</h1>
        })}
      </div>
    )
  }
}

export default SubProducts

编辑:

在使用 Sean Rileys 修复后,我正在尝试自己控制台日志 {product},现在我在控制台中遇到了这个问题,但仍然无法通过将 {product.img_url} 输出到那里是一个错误,“编译失败”

【问题讨论】:

  • 你不想在组件中为 selectedadditionalprod 设置状态,当 prop 是父组件本身的状态时
  • 您的问题是state.additonalprod 永远不会更新。当您的父组件已经在处理它时,您可以使用this.state.subproducts[this.props.additionalprod]

标签: javascript reactjs axios


【解决方案1】:

在初始渲染时,this.state.subproducts 为空,因此它无法在数组上运行 map 函数。只有在 API 调用之后,数组才会被数据填充。

这是一个非常常见的 React 问题,它是一个非常简单的解决方案,可以在运行方法之前检查数组是否为空。

{this.state.subproducts && this.state.subproducts[this.state.additionalprod].map((product) => {
  <h1>{product.img_url}</h1>
})}

this.state.subproducts &amp;&amp;... 只是检查数组是否返回真值,如果它不为空,它将运行,如果是,它将运行下一段代码。

另一个选项是“可选链接”,它几乎做同样的事情。

{this.state.subproducts[this.state.additionalprod]?.map((product) => {
  <h1>{product.img_url}</h1>
})}

注意map ?.map 前面的问号。通过在我们调用函数的数组后面添加问号,它只会在数组被定义的情况下运行,否则它将返回undefined,但您不会收到错误。

【讨论】:

  • 嗯,还是没有输出!用第二种方法,没有报错前端也没有输出?
  • 但是,如果我执行

    {console.log({ product })}

    ,它会将其记录到控制台!

    {console.log({ product.img_url })}

    不会工作
  • @DonnieBerry 你确定this.state.additionalprod 是想要的值吗?
  • 是的,我什至只尝试了 '5' 而不是 'this.state.additionalprod',这将从我的数据库中提取 ID 为 5 的所有内容。它可以工作,但它只是不会记录,我'将发布屏幕截图作为更新
【解决方案2】:

您必须在渲染之前等待响应,只需为您的数组添加长度检查:

componentDidMount() {
  this.setState({additionalprod: this.props.additionalprod}, () => {
    axios.get("http://localhost/api/subproducts.php").then((res) => {
      this.setState({ subproducts: res.data })
      console.log(this.state.subproducts[5])
    });
 }
}

render() {
  return (
    <div>
      {this.state.subproducts.length > 0 ? 
         this.state.subproducts[this.state.additionalprod].map((product) => 
            <h1>{product.img_url}</h1>
          }) : null 
    </div>
  )
 }

【讨论】:

  • 只删除地图函数中多余的引号
  • @DonnieBerry 在 compenetDidMount 中保存附加产品
猜你喜欢
  • 2018-02-16
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 2018-09-07
  • 2013-02-02
  • 2023-01-03
  • 1970-01-01
相关资源
最近更新 更多