reactjs 将对象数组渲染到列表中会出错
reactjs render array of objects into a list gives an error
所以我从获取的 json 文件创建一个对象,并在 showResult() 函数中我根据某些条件将一个对象添加到数组 finalArray 并将该数组传递给组件 Card,这应该呈现一个列表,但它给我一个错误 items.map is not a function ,但如果我改变
finalArray:this.state.finalArray.push(新用户(价格,位置,图片,姓名,分数))
至
finalArray: this.state.finalArray.concat(新用户(价格, 位置, 图片, 姓名, 分数))
然后它可以工作,但它只显示最后一个对象只显示 1 个列表项,这不是我想要的,有人可以帮助指出错误或如何正确地执行此操作,因为我是新来的反应和javascript
import React from 'react';
import Card from './Card.js';
export default class Slider extends React.Component {
constructor() {
super()
this.state = {
imgArray: [ "/img/work1.jpg", "/img/work2.jpg", "/img/work3.jpg"],
imgNo: 0,
url: "https://www.deskbookers.com/nl-nl/sajax.json?q=Amsterdam&type=-&people=any&favorite=0&pid=&sw=52.293753%2C4.634942&ne=52.455562%2C5.162286&ids=17201%2C19640%2C13692%2C13691%2C12136%2C17938%2C15292%2C14886%2C14885%2C14884%2C14883%2C15730%2C15353%2C15351%2C15330%2C15080%2C17290%2C15454%2C15451%2C15379",
current: "/img/work1.jpg",
search: '',
resultObject: null,
finalArray: [],
headlines: ["Pink Floyd Office", "Led Zeppelin Mania", "Central Perk Friends"],
headline : "Pink Floyd Office"
};
}
componentDidMount(){
this.serverRequest = $.get(this.state.url, function(result){
var info = result;
console.log(info);
this.setState({
resultObject:info
})
}.bind(this));
}
nextImg(){
if(this.state.imgNo < 2 && this.state.imgNo >=0 ){
this.setState({
imgNo : ++this.state.imgNo ,
current: this.state.imgArray[this.state.imgNo],
headline: this.state.headlines[this.state.imgNo]
})
}
}
prevImg(){
if(this.state.imgNo >= 1 && this.state.imgNo < 3 ){
this.setState({
imgNo : --this.state.imgNo,
current: this.state.imgArray[this.state.imgNo],
headline: this.state.headlines[this.state.imgNo]
})
}
}
searchQuery(e){
this.setState({
search: e.target.value
})
}
showResult(){
for(var i=0 ; i<this.state.resultObject.rows.length; i++){
if(this.state.search.toLowerCase() == this.state.resultObject.rows[i].location_city.toLowerCase()){
var price = this.state.resultObject.rows[i].day_price;
var location=(this.state.resultObject.rows[i].address[0]+", "+this.state.resultObject.rows[i].address[1]+", "+this.state.resultObject.rows[i].address[2]);
var image=this.state.resultObject.rows[i].image_urls2[0];
var name=this.state.resultObject.rows[i].location_name;
var score=this.state.resultObject.rows[i].location_rating;
if( price!=null && location!=null && image!=null && name!=null && score !=null){
function user(price, location, image, name, score){
this.price = price;
this.location = location;
this.image = image;
this.name = name;
this.score = score;
}
this.setState({
finalArray: this.state.finalArray.push(new user(price, location, image, name, score))
})
}
$(".card-list").show();
$('html,body').animate({
scrollTop: $(".card-list").offset().top},
'slow');
}
else{
$(".alert-box, .cancel").animate( { "opacity": "show", bottom:"0"} , 1250 );
$(".alert-box, .cancel").animate( { "opacity": "hide", bottom:"0"} , 3750 );
this.setState({
search: ""
})
$(".card-list").hide();
break;
}
}
}
render(){
return(
<div>
<div class="slider ">
<div class="img-container">
<img src={this.state.current} class="main-img" />
<div class="headline"><span>{this.state.headline}</span></div>
</div>
<img src="/img/slider-left.png" class="slider-arrow" onClick={this.prevImg.bind(this)} />
<img src="/img/slider-right.png" class="slider-arrow slider-right" onClick={this.nextImg.bind(this)} />
<div class="search-container">
<img src="/img/cancel.png" class="cancel hide"/>
<span class="alert-box hide">No offices available in this city, please try another one!</span>
<input onChange={this.searchQuery.bind(this)} value={this.state.search} type="text" name="search" placeholder="City name..." class="search-bar" />
<button disabled={!this.state.search} onClick={this.showResult.bind(this)} class="search-button">Sit me!</button>
</div>
</div>
<Card finalArray={this.state.finalArray}></Card>
</div>
);
}
}
import React from 'react';
export default class Card extends React.Component {
render(){
var items = this.props.finalArray;
var itemslist = items.map(function(item,index){
return(
<li key={index} class="card">
<img src={item.image} class="card-img" />
<div>
<div class="card-info">
<p class="workplace-name">{item.name}</p>
<span class="score">{item.score}</span>
<p class="location">{item.location}</p>
</div>
<div class="card-footer">
<p class="price">{item.price} €</p>
</div>
</div>
</li>
);})
return(
<ul class="card-list">
{ itemslist }
</ul>
);
}
}
The .push
method returns the new length of the array。所以当你做
this.setState({
finalArray: this.state.finalArray.push(...)
});
您正在将 this.state.finalArray
的值从 数组 更改为 数字 。当然数字没有 .map
方法。
如果要向数组中添加新元素并创建新数组,可以使用.concat
代替:
this.setState({
finalArray: this.state.finalArray.concat(...)
});
总的来说,您的代码似乎比实际情况要复杂。例如。 user
函数不需要,直接创建对象即可。 null
检查也可能是不必要的。
我不确定您希望您的代码如何工作,但对我来说 showResult
结果方法看起来应该像这样:
showResults() {
var search = this.state.search.toLowerCase();
var finalArray = this.state.resultObject.rows
.filter(row => search == row.location_city.toLowerCase())
.map(row => ({
price: row.day_price,
location: rows.address.slice(0,3).join(', '),
image: row.image_urls2[0],
name: row.location_name,
score: row.location_rating,
}))
.filter(user => user.price != null &&
user.image != null &&
user.name != null &&
user.score != null
);
this.setState(
{
finalArray,
search: finalArray.length > 0 ? this.state.search : '',
},
() => {
// This is executed after the component updated
if (finalArray.length > 0) {
$(".card-list").show();
$('html,body').animate({
scrollTop: $(".card-list").offset().top
}, 'slow');
} else {
$(".alert-box, .cancel").animate( { "opacity": "show", bottom:"0"} , 1250 );
$(".alert-box, .cancel").animate( { "opacity": "hide", bottom:"0"} , 3750 );
$(".card-list").hide();
}
}
);
}
也就是说,首先创建您的数据,对象数组并更新组件状态。更新后,检查是否有结果,是否根据该结果显示或隐藏列表。请注意,手动更改组件的样式不是您通常使用 React 执行的操作。
所以我从获取的 json 文件创建一个对象,并在 showResult() 函数中我根据某些条件将一个对象添加到数组 finalArray 并将该数组传递给组件 Card,这应该呈现一个列表,但它给我一个错误 items.map is not a function ,但如果我改变 finalArray:this.state.finalArray.push(新用户(价格,位置,图片,姓名,分数)) 至 finalArray: this.state.finalArray.concat(新用户(价格, 位置, 图片, 姓名, 分数))
然后它可以工作,但它只显示最后一个对象只显示 1 个列表项,这不是我想要的,有人可以帮助指出错误或如何正确地执行此操作,因为我是新来的反应和javascript
import React from 'react';
import Card from './Card.js';
export default class Slider extends React.Component {
constructor() {
super()
this.state = {
imgArray: [ "/img/work1.jpg", "/img/work2.jpg", "/img/work3.jpg"],
imgNo: 0,
url: "https://www.deskbookers.com/nl-nl/sajax.json?q=Amsterdam&type=-&people=any&favorite=0&pid=&sw=52.293753%2C4.634942&ne=52.455562%2C5.162286&ids=17201%2C19640%2C13692%2C13691%2C12136%2C17938%2C15292%2C14886%2C14885%2C14884%2C14883%2C15730%2C15353%2C15351%2C15330%2C15080%2C17290%2C15454%2C15451%2C15379",
current: "/img/work1.jpg",
search: '',
resultObject: null,
finalArray: [],
headlines: ["Pink Floyd Office", "Led Zeppelin Mania", "Central Perk Friends"],
headline : "Pink Floyd Office"
};
}
componentDidMount(){
this.serverRequest = $.get(this.state.url, function(result){
var info = result;
console.log(info);
this.setState({
resultObject:info
})
}.bind(this));
}
nextImg(){
if(this.state.imgNo < 2 && this.state.imgNo >=0 ){
this.setState({
imgNo : ++this.state.imgNo ,
current: this.state.imgArray[this.state.imgNo],
headline: this.state.headlines[this.state.imgNo]
})
}
}
prevImg(){
if(this.state.imgNo >= 1 && this.state.imgNo < 3 ){
this.setState({
imgNo : --this.state.imgNo,
current: this.state.imgArray[this.state.imgNo],
headline: this.state.headlines[this.state.imgNo]
})
}
}
searchQuery(e){
this.setState({
search: e.target.value
})
}
showResult(){
for(var i=0 ; i<this.state.resultObject.rows.length; i++){
if(this.state.search.toLowerCase() == this.state.resultObject.rows[i].location_city.toLowerCase()){
var price = this.state.resultObject.rows[i].day_price;
var location=(this.state.resultObject.rows[i].address[0]+", "+this.state.resultObject.rows[i].address[1]+", "+this.state.resultObject.rows[i].address[2]);
var image=this.state.resultObject.rows[i].image_urls2[0];
var name=this.state.resultObject.rows[i].location_name;
var score=this.state.resultObject.rows[i].location_rating;
if( price!=null && location!=null && image!=null && name!=null && score !=null){
function user(price, location, image, name, score){
this.price = price;
this.location = location;
this.image = image;
this.name = name;
this.score = score;
}
this.setState({
finalArray: this.state.finalArray.push(new user(price, location, image, name, score))
})
}
$(".card-list").show();
$('html,body').animate({
scrollTop: $(".card-list").offset().top},
'slow');
}
else{
$(".alert-box, .cancel").animate( { "opacity": "show", bottom:"0"} , 1250 );
$(".alert-box, .cancel").animate( { "opacity": "hide", bottom:"0"} , 3750 );
this.setState({
search: ""
})
$(".card-list").hide();
break;
}
}
}
render(){
return(
<div>
<div class="slider ">
<div class="img-container">
<img src={this.state.current} class="main-img" />
<div class="headline"><span>{this.state.headline}</span></div>
</div>
<img src="/img/slider-left.png" class="slider-arrow" onClick={this.prevImg.bind(this)} />
<img src="/img/slider-right.png" class="slider-arrow slider-right" onClick={this.nextImg.bind(this)} />
<div class="search-container">
<img src="/img/cancel.png" class="cancel hide"/>
<span class="alert-box hide">No offices available in this city, please try another one!</span>
<input onChange={this.searchQuery.bind(this)} value={this.state.search} type="text" name="search" placeholder="City name..." class="search-bar" />
<button disabled={!this.state.search} onClick={this.showResult.bind(this)} class="search-button">Sit me!</button>
</div>
</div>
<Card finalArray={this.state.finalArray}></Card>
</div>
);
}
}
import React from 'react';
export default class Card extends React.Component {
render(){
var items = this.props.finalArray;
var itemslist = items.map(function(item,index){
return(
<li key={index} class="card">
<img src={item.image} class="card-img" />
<div>
<div class="card-info">
<p class="workplace-name">{item.name}</p>
<span class="score">{item.score}</span>
<p class="location">{item.location}</p>
</div>
<div class="card-footer">
<p class="price">{item.price} €</p>
</div>
</div>
</li>
);})
return(
<ul class="card-list">
{ itemslist }
</ul>
);
}
}
The .push
method returns the new length of the array。所以当你做
this.setState({
finalArray: this.state.finalArray.push(...)
});
您正在将 this.state.finalArray
的值从 数组 更改为 数字 。当然数字没有 .map
方法。
如果要向数组中添加新元素并创建新数组,可以使用.concat
代替:
this.setState({
finalArray: this.state.finalArray.concat(...)
});
总的来说,您的代码似乎比实际情况要复杂。例如。 user
函数不需要,直接创建对象即可。 null
检查也可能是不必要的。
我不确定您希望您的代码如何工作,但对我来说 showResult
结果方法看起来应该像这样:
showResults() {
var search = this.state.search.toLowerCase();
var finalArray = this.state.resultObject.rows
.filter(row => search == row.location_city.toLowerCase())
.map(row => ({
price: row.day_price,
location: rows.address.slice(0,3).join(', '),
image: row.image_urls2[0],
name: row.location_name,
score: row.location_rating,
}))
.filter(user => user.price != null &&
user.image != null &&
user.name != null &&
user.score != null
);
this.setState(
{
finalArray,
search: finalArray.length > 0 ? this.state.search : '',
},
() => {
// This is executed after the component updated
if (finalArray.length > 0) {
$(".card-list").show();
$('html,body').animate({
scrollTop: $(".card-list").offset().top
}, 'slow');
} else {
$(".alert-box, .cancel").animate( { "opacity": "show", bottom:"0"} , 1250 );
$(".alert-box, .cancel").animate( { "opacity": "hide", bottom:"0"} , 3750 );
$(".card-list").hide();
}
}
);
}
也就是说,首先创建您的数据,对象数组并更新组件状态。更新后,检查是否有结果,是否根据该结果显示或隐藏列表。请注意,手动更改组件的样式不是您通常使用 React 执行的操作。