Как решить TypeError: Не удается прочитать свойство 'map' из undefined? - PullRequest
1 голос
/ 15 апреля 2020

Я получаю эту ошибку

TypeError: Невозможно прочитать свойство 'map' из undefined`

DISHES объект импортирован из блюд . js и загружается в объекты состояния состояния в приложении . js Компонент, а затем передается как реквизиты MenuComponent. js через компонент меню, когда отображается в приложении. js

Я не знаю, почему, все кажется правильным, это задание является частью онлайн-курса, и я видел исправления, сделанные другими люди, которые прошли курс, и они, кажется, делают то же самое, что и я, и это работает для них.

Вывод :

enter image description here

Приложение. js

import React, {Component} from 'react';
import {Navbar, NavbarBrand} from 'reactstrap';
import './App.css';
import Menu from './components/MenuComponent';
import { DISHES } from "./shared/dishes";


class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      dishes: DISHES
    };
  }
  render() {
    return (
      <div>
        <Navbar dark color="primary">
          <div className="container">
            <NavbarBrand href="/">Ristorante Con Fusion</NavbarBrand>
          </div>
        </Navbar>
        <Menu dishes={this.state.dishes}/>
      </div>
    );
  }
}

export default App;

Компонент меню. js

import React, { Component } from 'react';
import { Card, CardImg, CardImgOverlay, CardText, CardBody, CardTitle } from 'reactstrap';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedDish: null
    };
  }

  onDishSelect(dish) {
    this.setState({selectedDish: dish});
  }

  renderDish(dish) {
    if (dish != null) {
      return (
        <Card>
          <CardImg width="100%" src={dish.image} alt={dish.name}/>
          <CardBody>
            <CardTitle>{dish.name}</CardTitle>
            <CardText>{dish.description}</CardText>
          </CardBody>
        </Card>
      );
    } else {
      return (
        <div></div>
      );
    }
  }

  render() {
    const menu = this.props.dishes.map((dish) => {
      return (
        <div key={dish.id} className="col-12 col-md-5 m-1">
          <Card onClick={() => this.onDishSelect(dish)}>
            <CardImg width="100%" src={dish.image} alt={dish.name}/>
            <CardImgOverlay>
              <CardTitle>{dish.name}</CardTitle>
            </CardImgOverlay>
          </Card>
        </div>
      );
    });

    return (
      <div className="container">
        <div className="row">
          {menu}
        </div>
        <div className="row">
          {this.renderDish(this.state.selectedDish)}
        </div>
      </div>
    );
  }
}

export default Menu;

блюда. js

export const DISHES =
[
    {
    id: 0,
    name:'Uthappizza',
    image: 'assets/images/uthappizza.png',
    category: 'mains',
    label:'Hot',
    price:'4.99',
    description:'A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.',
    comments: [
        {
        id: 0,
        rating: 5,
        comment: "Imagine all the eatables, living in conFusion!",
        author: "John Lemon",
        date: "2012-10-16T17:57:28.556094Z"
        },
        {
        id: 1,
        rating: 4,
        comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
        author: "Paul McVites",
        date: "2014-09-05T17:57:28.556094Z"
        },
        {
        id: 2,
        rating: 3,
        comment: "Eat it, just eat it!",
        author: "Michael Jaikishan",
        date: "2015-02-13T17:57:28.556094Z"
        },
        {
        id: 3,
        rating: 4,
        comment: "Ultimate, Reaching for the stars!",
        author: "Ringo Starry",
        date: "2013-12-02T17:57:28.556094Z"
        },
        {
        id: 4,
        rating: 2,
        comment: "It's your birthday, we're gonna party!",
        author: "25 Cent",
        date: "2011-12-02T17:57:28.556094Z"
        }
    ]                        },
    {
    id: 1,
    name:'Zucchipakoda',
    image: 'assets/images/zucchipakoda.png',
    category: 'appetizer',
    label:'',
    price:'1.99',
    description:'Deep fried Zucchini coated with mildly spiced Chickpea flour batter accompanied with a sweet-tangy tamarind sauce',
    comments: [
        {
        id: 0,
        rating: 5,
        comment: "Imagine all the eatables, living in conFusion!",
        author: "John Lemon",
        date: "2012-10-16T17:57:28.556094Z"
        },
        {
        id: 1,
        rating: 4,
        comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
        author: "Paul McVites",
        date: "2014-09-05T17:57:28.556094Z"
        },
        {
        id: 2,
        rating: 3,
        comment: "Eat it, just eat it!",
        author: "Michael Jaikishan",
        date: "2015-02-13T17:57:28.556094Z"
        },
        {
        id: 3,
        rating: 4,
        comment: "Ultimate, Reaching for the stars!",
        author: "Ringo Starry",
        date: "2013-12-02T17:57:28.556094Z"
        },
        {
        id: 4,
        rating: 2,
        comment: "It's your birthday, we're gonna party!",
        author: "25 Cent",
        date: "2011-12-02T17:57:28.556094Z"
        }
    ]
    },
    {
    id: 2,
    name:'Vadonut',
    image: 'assets/images/vadonut.png',
    category: 'appetizer',
    label:'New',
    price:'1.99',
    description:'A quintessential ConFusion experience, is it a vada or is it a donut?',
    comments: [
        {
        id: 0,
        rating: 5,
        comment: "Imagine all the eatables, living in conFusion!",
        author: "John Lemon",
        date: "2012-10-16T17:57:28.556094Z"
        },
        {
        id: 1,
        rating: 4,
        comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
        author: "Paul McVites",
        date: "2014-09-05T17:57:28.556094Z"
        },
        {
        id: 2,
        rating: 3,
        comment: "Eat it, just eat it!",
        author: "Michael Jaikishan",
        date: "2015-02-13T17:57:28.556094Z"
        },
        {
        id: 3,
        rating: 4,
        comment: "Ultimate, Reaching for the stars!",
        author: "Ringo Starry",
        date: "2013-12-02T17:57:28.556094Z"
        },
        {
        id: 4,
        rating: 2,
        comment: "It's your birthday, we're gonna party!",
        author: "25 Cent",
        date: "2011-12-02T17:57:28.556094Z"
        }
    ]
    },
    {
    id: 3,
    name:'ElaiCheese Cake',
    image: 'assets/images/elaicheesecake.png',
    category: 'dessert',
    label:'',
    price:'2.99',
    description:'A delectable, semi-sweet New York Style Cheese Cake, with Graham cracker crust and spiced with Indian cardamoms',
    comments: [
        {
        id: 0,
        rating: 5,
        comment: "Imagine all the eatables, living in conFusion!",
        author: "John Lemon",
        date: "2012-10-16T17:57:28.556094Z"
        },
        {
        id: 1,
        rating: 4,
        comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
        author: "Paul McVites",
        date: "2014-09-05T17:57:28.556094Z"
        },
        {
        id: 2,
        rating: 3,
        comment: "Eat it, just eat it!",
        author: "Michael Jaikishan",
        date: "2015-02-13T17:57:28.556094Z"
        },
        {
        id: 3,
        rating: 4,
        comment: "Ultimate, Reaching for the stars!",
        author: "Ringo Starry",
        date: "2013-12-02T17:57:28.556094Z"
        },
        {
        id: 4,
        rating: 2,
        comment: "It's your birthday, we're gonna party!",
        author: "25 Cent",
        date: "2011-12-02T17:57:28.556094Z"
        }
    ]
    }
];

Ответы [ 2 ]

2 голосов
/ 15 апреля 2020

У вас есть этот компонент <Menu dishes={this.state.dishes}/>, который ожидает dishes проп.

Теперь в <App> вы вызываете this.setState(), но он асинхронный, и при первом рендере <App> ( и поэтому <Menu>) значение this.state.dishes по-прежнему undefined, следовательно, this.props в <Menu> также undefined

Когда оно обновляется, происходит повторный рендеринг, <App> и <Menu> отображаются с правильными значениями.

Таким образом, вы можете добавить проверку для undefined, чтобы .map() выполнялся только тогда, когда this.props имеет значение.

Вот что делает this.props && this.props.dishes.map(). По сути это означает if(this.props){ this.props.dishes.map() }, поэтому, когда this.props равно undefined, второе выражение не выполняется.

После завершения setState определяется this.props, и вы получаете свой результат.

1 голос
/ 15 апреля 2020

Чтобы избежать любых неопределенных значений реквизита, вы можете использовать библиотеку prop-types , в которой вы определяете значения по умолчанию для реквизита, так что если значение реквизита не будет передано вашему компоненту, ваш компонент все равно будет иметь значение по умолчанию, чтобы вести себя как ожидалось. Это полезно в том случае, если ваши реквизиты не определены, например, с самого начала (что, вероятно, имеет место здесь).

Для этого установите библиотеку:

npm install --save prop-types

Затем в вашем файле MenuComponent добавьте импорт в начало вашего файла:

import PropTypes from 'prop-types';

и, наконец, в конце вашего файла добавьте эту проверку типа реквизита и значение по умолчанию:

// Define the props types to check
Menu.propTypes = {
  dishes: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number,
    name: PropTypes.string,
    image: PropTypes.string,
    category: PropTypes.string,
    label: PropTypes.string,
    price: PropTypes.string,
    description: PropTypes.string,
    comment: PropTypes.arrayOf(PropTypes.shape({
      id: PropTypes.number,
      rating: PropTypes.number,
      comment: PropTypes.string,
      author: PropTypes.string,
      date: PropTypes.string,
    })),
  })),
};

// Define here the default value to attribute to your dishes props
Menu.defaultProps = {
  dishes: [],
};

export default Menu;

Надеюсь, это поможет!

...