如何解决 TypeError:无法读取未定义的属性“map”?
我一直收到此错误
TypeError: Cannot read property 'map' of undefined`
DISHES
对象从
dishes.js
导入并加载到
App.js
组件中的状态对象 dishes 中,然后在
App.js
中呈现时,它通过 Menu 组件作为 props 传递给
MenuComponent.js
我不知道为什么,一切似乎都正确,这是一项在线课程的作业,我已经看到其他参加该课程的人所做的更正,他们似乎在做与我完全一样的事情,并且对他们有效。
输出 :
App.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;
MenuComponent.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;
dishes.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"
}
]
}
];
您有此组件
<Menu dishes={this.state.dishes}/>
,它需要一个
dishes
prop。
现在在
<App>
中,您调用
this.setState()
,但它是异步的,并且在第一次渲染
<App>
(以及
<Menu>
)时,
this.state.dishes
的值仍然为
undefined
,因此
<Menu>
中的
this.props
也是
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
被定义,并且您将获得结果。
为了避免任何 props 未定义值,您可以使用库 prop-types ,在其中定义您的 props 默认值,这样如果 props 值未传输到您的组件,您的组件仍将具有默认值以按预期运行。例如,在您的 props 从一开始就没有定义的情况下(这可能是这里的情况),它很有用。
为此,请安装库:
npm install --save prop-types
然后在您的
MenuComponent
文件中,在文件顶部添加导入:
import PropTypes from 'prop-types';
最后,在文件末尾,添加此 props 类型检查和默认值:
// 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;
希望这对您有帮助!
我正在上同一门课,我复制并粘贴了你的代码,没有任何问题。请确保你的 index.js 文件也像这样。如果这不是问题,那么你的导入可能已正确安装。由于 MenuComponent 存在问题,因此可能 React 未正确下载。
不确定问题是什么,但我不认为这是代码的问题。
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();