[英]Why 'map' function is showing undefined error even though it is defined?
I am using React with NodeJS and MongoDB to integrate FE with BE.我正在使用带有 NodeJS 和 MongoDB 的 React 将 FE 与 BE 集成。 I am working on Homepage and its divided in 4 phases.
我正在开发主页,它分为 4 个阶段。
Home.js主页.js
import React, {Component} from 'react';
import axios from 'axios';
import '../Styles/Home.css';
import HomeUH from './HomeUH';
import HomeLH from './HomeLH';
class Home extends React.Component
{
constructor()
{
super();
this.state={
cities: [],
widgets: []
};
}
componentDidMount()
{
axios.get('http://localhost:4005/api/locationDD')
.then(result => {
this.setState({
cities: result.data.locations
})
}).catch(error => {
console.log(error);
})
axios.get('http://localhost:4005/api/widget')
.then(result => {
this.setState({
widgets: result.data.widget
})
}).catch(error => {
console.log(error);
})
}
render()
{
const { cities, widgets } = this.state;
return(
<div>
<HomeUH cities={cities}/>
<HomeLH widgets={widgets}/>
</div>
);
}
}
export default Home;
HomeUH.js主页UH.js
import React, {Component} from 'react';
import '../Styles/Home.css';
import homewall from '../Images/homewall.jpg';
class HomeUH extends React.Component
{
constructor()
{
super();
}
render()
{
const { cities } = this.props;
return(
<React.Fragment>
<img className="homewall" src={homewall} height="50%" width="100%"/>
<div className="logo">
Sample
</div>
<div className="heading">
Find the best Schools & Colleges
</div>
<div className="search">
<select className="locdd">
<option value="0" selected disabled>Select Location</option>
{
cities.map((city, index) => {
return <option value={city.city_id} key={index}>{city.name}</option>
})
}
</select>
<div style={{position: 'relative', float: 'right'}}>
<span className="glyphicon glyphicon-search" style={{position: 'absolute', fontSize: '2rem', top: '40px', left: '35px'}}></span>
<input className="restInput" type="text" placeholder="Enter School/College Name" style={{paddingLeft: '50px'}}/>
</div>
</div>
<br/><br/>
</React.Fragment>
);
}
}
export default HomeUH;
HomeLH.js主页LH.js
import React, {Component} from 'react';
import '../Styles/Home.css';
import QSItem from './QSItem';
class HomeLH extends React.Component
{
constructor()
{
super();
}
render()
{
const { widgets } = this.props;
return(
<React.Fragment>
<a id="heading1">Quick Searches</a> <br/>
<a id="heading2">Discover different Colleges by Streams </a> <br/><br/>
<div className="container-fluid" style={{minWidth: '1000px', margin: 'auto'}}>
<div className="row">
{
widgets.map((widget, index) => {
return <QSItem key={index} widget={widget}></QSItem>
})
}
</div>
</div>
</React.Fragment>
);
}
}
export default HomeLH;
QSItem.js QSItem.js
import React, {Component} from 'react';
import '../Styles/Home.css';
class QSItem extends React.Component
{
render()
{
const {widget} = this.props;
const img = require(`../${widget.image}`).default;
return(
<div className="col-sm-4 col-md-4 col-lg-4">
<div className="card mb-3" style={{maxWidth: '540px', marginLeft: '35px'}}>
<div className="row quicksearch" style={{paddingLeft: '1px', paddingBottom: '1px'}}>
<div className="col-md-4">
<img className="card-img" src={img} alt="" height="100%" style={{width: '140px', margin: 'auto'}}/>
</div>
<div className="col-md-8" style={{float: 'right'}}>
<div className="card-body">
<div className="tileheading">
{widget.name}
</div>
<div className="tilesubheading">
{widget.content}
</div>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default QSItem;
If you see in HomeUH.js in I applied map function for cities and it went well.如果您在 HomeUH.js 中看到我为城市应用了 map function 并且进展顺利。 But when I done same process in HomeLH.js for widget its showing error "Cannot read property 'map' of undefined" even though it is defined in 'widgets'.
但是,当我在 HomeLH.js 中为小部件执行相同的过程时,它显示错误“无法读取未定义的属性 'map'”,即使它是在“小部件”中定义的。
Your problem is that you "override" your state with this.setState
, You can use a callback to use previous state and merge your new value with the old state:您的问题是您使用 this.setState “覆盖”您的
this.setState
,您可以使用回调来使用以前的 state 并将您的新值与旧的 state 合并:
componentDidMount()
{
axios.get('http://localhost:4005/api/locationDD')
.then(result => {
this.setState(prevState => ({
...prevState,
cities: result.data.locations
}))
}).catch(error => {
console.log(error);
})
axios.get('http://localhost:4005/api/widget')
.then(result => {
this.setState(prevState => ({
...prevState,
widgets: result.data.widget
}))
}).catch(error => {
console.log(error);
})
}
This should prevent your widgets
to ever be undefined
.这应该可以防止您的
widgets
永远是undefined
。
Another possible solution is to wait for both request to end before setting the data, this can be achieved with Promise.all
:另一种可能的解决方案是在设置数据之前等待两个请求结束,这可以通过
Promise.all
来实现:
Promise.all([
axios.get('http://localhost:4005/api/locationDD'),
axios.get('http://localhost:4005/api/widget'),
])
.then(([locationResult, widgetResult]) => {
this.setState({
widgets: widgetResult.data.widget,
cities: locationResult.data.locations
})
}).catch(error => {
console.log(error);
})
In this case you will only update your state once.在这种情况下,您只需更新一次 state。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.