reactjs выводит массив объектов в список с ошибкой

#javascript #arrays #object #reactjs #frontend

#javascript #массивы #объект #reactjs #интерфейс

Вопрос:

итак, я создаю объект из выбранного файла json и в функции showResult () добавляю объект на основе некоторых условий в массив finalArray и передаю этот массив на компонентную карту, и это должно отобразить список, но это выдает ошибку items.map — это не функция, но также, если я изменю finalArray: this.state.finalArray.push(новый пользователь (цена, местоположение, изображение, имя, оценка)) на finalArray: this.state.finalArray.concat(новый пользователь (цена, местоположение, изображение, имя, оценка))

затем это работает, но только тогда отображается последний объект, показывающий только 1 элемент списка, который не является тем, что я хочу, может кто-нибудь помочь с указанием ошибки или как это сделать правильно, поскольку я новичок в react и 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=Amsterdamamp;type=-amp;people=anyamp;favorite=0amp;pid=amp;sw=52.293753,4.634942amp;ne=52.455562,5.162286amp;ids=17201,19640,13692,13691,12136,17938,15292,14886,14885,14884,14883,15730,15353,15351,15330,15080,17290,15454,15451,15379",
        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 =  resu<
    console.log(info);
    this.setState({
      resultObject:info
    })
  }.bind(this));
 }

  nextImg(){
    if(this.state.imgNo < 2 amp;amp; 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  amp;amp; 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 amp;amp; location!=null amp;amp; image!=null amp;amp; name!=null amp;amp; 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} amp;euro;</p>
                  </div>
                </div>
              </li>
          );})
    return(
      <ul class="card-list">
        { itemslist }
       </ul> 

      );

  }
}
  

Ответ №1:

.push Метод возвращает новую длину массива. Поэтому, когда вы делаете

 this.setState({
    finalArray: this.state.finalArray.push(...)
});
  

вы меняете значение this.state.finalArray из массива на число. Конечно, у numbers нет .map метода.

Если вы хотите добавить новый элемент в массив и создать новый массив, вы можете использовать .concat вместо:

 this.setState({
    finalArray: this.state.finalArray.concat(...)
});
  

В целом ваш код выглядит более сложным, чем должен быть. Например. user функция не нужна, просто создайте объект напрямую. null Проверки также могут быть ненужными.

Я не совсем уверен, как вы ожидаете, что ваш код будет работать, но мне кажется, что showResult метод results скорее должен выглядеть следующим образом:

 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 amp;amp;
      user.image != null amp;amp;
      user.name != null amp;amp;
      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.

Комментарии:

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

2. Ах, я не заметил, что ваш код находится внутри цикла. Позвольте мне обновить мой ответ.

3. Обновил мой ответ.

4. я заменил свою функцию showResult на вашу, но теперь, когда я нажимаю кнопку, она буквально ничего не делает, даже не выдает ошибку или что-либо в консоли @Felix Kling

5. о, извините, это была моя ошибка, все работает отлично, большое вам спасибо