0
votes

I'm getting an error while rendering using map functions. It shows:

typeError Cannot read property 'map' of undefined

Here is my all component files:

Menu component.js

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

    import DishDetail from './DishdetailComponent';

    class Menu extends Component {

        constructor(props) {
            super(props);
        }

        renderDish(dish) {
            if(dish != null){
                return(
                    <DishDetail dish={dish}/>
                );
            }
            else{
                return(
                    <div></div>
                )
            }
        }

        render() {
            const menu = this.props.dishes.map((dish) => {
                return (
                <div className="col-12 col-md-5 m-1">
                    <Card key={dish.id} onClick={() => this.props.onClick(dish.id)}>
                    
                    <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>
            );
        }
    }

    export default Menu;

DishdetailComponent.js

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


    class DishDetail  extends Component{

        constructor(props) {
            super(props);

            this.state = {
                selectedDish: null
            }
        }

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

        renderComments(comments){
            if(comments != null){
                return(
                    <div className="container">
                        <h4>Comments</h4>
                        {comments.map((comment) => {
                            let date = new Intl.DateTimeFormat('en-US', {
                                year:'numeric',
                                month: 'short',
                                day: '2-digit'
                            }).format(new Date(Date.parse(comment.date)))
                            return(
                                <ul className="list-unstyled" key={comment.id}>
                                    <li className="comment">{comment.comment}</li>
                                    <br/>
                                    <li className="author">-- {comment.author}, {date}</li>
                                </ul>
                            );
                            })}
                    </div>
                )

            }
            else{
                return(
                    <div></div>
                )
            }
        }

        render(){

            const selectedDish = this.props.dish;

            return(
                <div className="container">
                    <div className="row">
                        <div className="col-12 col-md-5 m-1">
                            {this.renderDish(selectedDish)}
                        </div>
                        <div className="col-12 col-md-5 m-1">
                            {this.renderComments(selectedDish.comments)}
                        </div>
                    </div>
                </div>
            )
        }

    }

    export default DishDetail;

MainComponent.js

    import React,{ Component } from 'react';
    import { Navbar, NavbarBrand } from 'reactstrap';
    import Menu from './MenuComponents';
    import DishDetail from './DishdetailComponent'
    import { DISHES } from '../shared/shareDishes.js';

    class Main extends Component {

    constructor(props) {
        super(props);

        this.state = {
        dishes: DISHES,
        selectedDish: null 
        }; 
    }

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

    render() {
        return (
        <div>
            <Navbar dark color="primary">
            <div className="container">
                <NavbarBrand href="/">Ristorante confusion</NavbarBrand>
            </div>
            </Navbar>
            <Menu dishes = {this.state.dishes} 
                onClick={(dishId) => this.onDishSelect(dishId)} />
            <DishDetail dish={this.state.dishes.filter((dish) => dish.id === this.state.selectedDish[0])}/>
        </div>
        );
    }
    
    }

    export default Main;

Here is the sharedDishes.js file

    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"
                }
            ]
            }
    ] 

i get the data from array object in another file using id and iterate it using map function. but while render function it shows TypeError i've checked but i cant find the undefinded property. How to solve this?

2

2 Answers

1
votes

Ensure dishes and comments is truthy and is an Array:

Array.isArray(this.props.dishes)  && this.props.dishes.map(...)


Array.isArray(comments) && comments.map(...)

Good Luck...

0
votes

Try changin' selectedDish value from null to 0 while initializing state in your Main.js component.

  this.state = {
        dishes: DISHES,
        selectedDish: 0 
        }; 
    }

Also, move up key={dish.id} from Card to wrapping div

<div className="col-12 col-md-5 m-1" key={dish.id}>

CodeSandbox

In the DishDetail.js component, the next part is redundant (actually both constructors, in Menu and DishDetail, at the moment)

 this.state = {
   selectedDish: null
  }; 

as the component is receiving selectedDish as a prop from the Main.js component.

Hope this will get you going.

I'd suggest sticking to the convention of naming your files the same as your components. For example, DishDetail.js for class DishDetail extends..., Menu.js for class Menu extends... and creating components folder in your source directory - src/components/ for those component files.

All the best!