繁体   English   中英

TypeError:无法读取未定义的属性(读取“地图”) - State 返回未定义

[英]TypeError: Cannot read properties of undefined (reading 'map') - State returns undefined

我试图在 state 中检索一个数组,然后在 map 中检索 go,但返回未定义。 state 似乎还没有准备好,但不知道为什么。

我尝试了很多替代方案,但即使是我无法获得的长度,它也返回未定义。 只有 function getProductDetails 中的数据我可以得到长度,没有其他地方。 所以这就是为什么我认为这与 state 准备就绪有关,但不知道如何解决。

任何帮助,将不胜感激。

import React, { Component } from 'react';
import propTypes from 'prop-types';
import { Link } from 'react-router-dom';
import cartIcon from '../images/cartIcon.jpg';
import backIcon from '../images/backIcon.jpg';
import '../styles/ProductDetails.css';

export default class ProductDetails extends Component {
  constructor() {
    super();
    this.state = {
      product: {},
    };
  }

  componentDidMount() {
    this.getDetails();
  }

  async getProductDetails(item) {
    const url = `https://api.mercadolibre.com/items/${item}`;
    const response = await fetch(url);
    const data = await response.json();
    return data;
  }

  async getDetails() {
    const { match: { params: { id } } } = this.props;
    const product = await this.getProductDetails(id);
    this.setState({
      product,
    });
  }

  render() {
    const { product } = this.state;

    return (
      <section className="details">
        <div className="details__header">
          <div className="details__back">
            <Link
              to="/"
              className="back__btn"
              data-testid="shopping-back-button"
            >
              <img
                id="back-button"
                name="back-button"
                alt="Voltar"
                src={ backIcon }
                className="back__img"
              />
            </Link>
          </div>
          <div className="details__cart">
            <Link
              to="/carrinho-de-compras"
              className="cart__btn"
              data-testid="shopping-cart-button"
            >
              <img
                id="cart-button"
                name="cart-button"
                alt="Carrinho de Compras"
                src={ cartIcon }
                className="cart__img"
              />
            </Link>
          </div>
        </div>
        <div className="details__product">
          <div className="details__left">
            <p data-testid="product-detail-name">{ product.title }</p>
            <img src={ product.thumbnail } alt={ product.title } />
            <p>{ product.id }</p>
            <p>{ product.price }</p>
          </div>
          <div className="details__right">
            <ul>
              {(product.attributes)
                .map(({ name, value_name: valueName }, index) => (
                  <li key={ index }>
                    {name}
                    :
                    {valueName}
                  </li>))}
            </ul>
          </div>
        </div>
      </section>
    );
  }
}

ProductDetails.propTypes = {
  match: propTypes.shape({
    params: propTypes.shape({
      id: propTypes.string,
    }),
  }).isRequired,
};

那是因为您的this.state.product只有在您调用this.getDetails()以在componentDidMount中获取和设置数据后才可用。

因此,当您的组件第一次渲染(又名挂载)时, this.state.product将不可用。

为了解决这个问题,一种常见的方法是在render()方法中检查this.state.product像这样。

  render() {
    const { product } = this.state;

    // if data is NOT available
    if (!product) {
      // either return null, or render a loading indicator, or whatever you want, while waiting for `this.state.product` to be available
      return null
    }
    
    // if data is available
    return (
      <section className="details">
        // render your component here
      </section>
    );
  }

初始this.state.product值是一个空的 object {} ,所以this.state.product.attributes在初始渲染上是未定义的并且不可映射

this.state = {
  product: {},
};

product.titleproduct.idproduct.price在初始渲染中也是未定义的 OFC,但由于您没有更深入地访问,因此这些仅作为未定义值渲染到 DOM 并且不会引发错误。

您有几个选项可以防止可能的 null/undefined 访问:

  1. this.state.product.attributes上使用 null-check/guard-clause

     <ul> {product.attributes && product.attributes.map(({ name, value_name: valueName }, index) => ( <li key={index}> {name}: {valueName} </li> ))} </ul>
  2. this.state.product.attributes上使用可选的链接运算符

    <ul> {product.attributes?.map(({ name, value_name: valueName }, index) => ( <li key={index}> {name}: {valueName} </li> ))} </ul>

getProductDetails(item)不会返回 promise,因此 getDetails() 中的getDetails() await this.getProductDetails(id)不会等待任何东西。 您必须在 getProductDetails 中返回 Promise,如下所示:

async getProductDetails(item) {
return new Promise(async (resolve, reject) => {
  const url = `https://api.mercadolibre.com/items/${item}`;
  const response = await fetch(url);
  const data = await response.json();
  resolve(data)
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM