Реакция: Попытка установить ответ API JSON на объект состояния и передать его компоненту для отображения и рендеринга. - PullRequest
0 голосов
/ 11 марта 2019

У меня есть компонент, в котором я установил пустой массив с именем customers: [] в this.setState: { }. При загрузке компонент запускает вызов POST для API, который возвращает объект JSON с именем XHR CustomerOffers . У меня есть логика для перебора массива и сопоставления всех частей объекта JSON с пользовательским интерфейсом, но каждый раз, когда я загружаю приложение, я получаю сообщение об ошибке с указанием TypeError: this.state.customers.map is not a function, но когда я проверил это с фиктивными данными внутри клиенты выкладывают все правильно. Я использовал оператор console.log, чтобы напечатать ответ возврата из API, и он отображается как неопределенный, что наводит меня на мысль, что где-то в процессе возврата приложение не получает данные. Я включил свой код ниже, любая помощь по этому вопросу будет огромной!

Реагировать

import React, { Component } from 'react';
import './Button.css';
import Grid from '@material-ui/core/Grid';
import axios from 'axios';

class UsersList extends Component {


  constructor(){
        super();
        // this.selectCard  = this.selectCard.bind(this);
        // Define data model object and cardActive 
        this.state = {

            cardActive: null,

            dataModel: {
              offerName: null,
              customerId: null
            },

            SessionId: null,

            customers: []
        }



        // this.updateOffer = offerID => {};

        this.submitData = () => {
          let temporalDataModel = this.state.dataModel;

          temporalDataModel.SessionId = this.state.SessionId;

          console.log(
            "Transmitting data...NOW",
            temporalDataModel
          );

          this.setState(
            {
              dataModel: temporalDataModel
            },
            () => {
              let postUrl = "https://myAPI.com";
              axios
                .post(postUrl, this.state.dataModel)
                .then(response => {
                  console.log(response);
                })
                .catch(err => {
                  console.error(err);
                });
            }
          );
        };

        this.selectCard = obj => {
          let temporalDataModel = this.state.dataModel;

        //   console.log("paramenters", obj);
        //   console.log("currentState", temporalDataModel);

          this.state.customers.forEach(c => {
            if (c.CustomerId === obj.customerId) {
              c.Offers.forEach(off => {
                if (off.OfferId === obj.offerId) {
                  console.log("offer", off);
                  temporalDataModel.customerId = obj.customerId;
                  temporalDataModel.offerName = off.Name;
                  temporalDataModel.offerId = off.OfferId;
                  temporalDataModel.products = off.Products;
                  temporalDataModel.sessionId = obj.SessionId;
                }
              });
            }
          });

          console.log("data updated", temporalDataModel);

          this.setState({ cardActive: obj.offerId, SessionId: obj.SessionId,  });
        };
    }


    getCustomerOffers(){
      var search = window.location.search;
      var params = new URLSearchParams(search);
      var customerId = params.get('CUSTOMERID');
      var sessionId = params.get('SESSIONID');
      var data = "{'CustomerId':'1','SessionId':'9636','IsExisting':'true'}";

      var requestOffers = { 
        method: 'post',
        url: 'https://myAPI.com',
        data: "{'CustomerId':'" + customerId + "','SessionId':'" + sessionId + "'}"
    };


          axios.post('https://myAPI.com',
               "{'CustomerId':'" + customerId + "','SessionId':'" + sessionId + "'}")
           .then((res) => {
               console.log("RESPONSE RECEIVED: ", res);
               this.setState({
                   customers: res.data
               });
               console.log("Customer: ", this.state.customers.CustomerId);
           })
           .catch((err) => {
               console.log("AXIOS ERROR: ", err);
           });

    }


    componentDidMount(){
      this.getCustomerOffers();

    }


    // selectCard(offerId) {   
    //     this.setState({ cardActive: offerId });
    //   }


    render (){
        return (
          this.state.customers != null && 
          <div>
          {this.state.customers.map((customer, index) => {
              return  <div key={index + customer.CustomerId}>

                              <h3 >Name: {customer.LastName}, {customer.FirstName}</h3>
                              <h3 >Customer ID: {customer.CustomerId}</h3>
                              <h3 >
                              Address: 
                              <br></br>
                              {customer.Address.Address1}
                              <br></br>
                              {customer.Address.City}, {customer.Address.State} {customer.Address.Zip} 
                              </h3>
                              <br></br>
                              <h2>Available Offers</h2>
                              <Grid container spacing={24} justify="center"> 
                              {customer.Offers.map((Offer,index) => {
                                  return <div key={index + Offer.OfferId} onClick={() => {
                                      const obj = {
                                        offerId: Offer.OfferId,
                                        customerId: customer.CustomerId,
                                      };
                                      console.log("Offer ID:",Offer.OfferId, ",Customer ID:",customer.CustomerId,",Offer Name:", Offer.OfferName, ",Session ID:", customer.SessionId);
                                      this.selectCard(obj);
                                    }}>
                                          <Grid item xs={12}>
                                          <div className={Offer.OfferId === this.state.cardActive ? "cardActive" : "card"}>
                                              <div className="container">
                                                  <h5><b>{Offer.OfferId}</b></h5> 
                                                  <h2>{Offer.Name}</h2>
                                                  {Offer.Products.map((Product, index) => {
                                                      return <div key={index + Product.ProductId}>
                                                              <p>+ {Product.ProductName}</p>
                                                            </div>

                                                  })}
                                                  <h3>{Offer.Price}</h3> 
                                              </div>
                                          </div>
                                          </Grid>

                                      </div>
                              })}

                              </Grid>

                      </div>

          })}

          <button className="navbuttonSelected" disabled={!this.state.cardActive} onClick={this.submitData}>Submit</button>

      </div>
        )

    }
}

export default UsersList

Ответы [ 2 ]

2 голосов
/ 11 марта 2019

Я не думаю, что вы используете Axios (или пытаетесь поймать), как это должно быть для асинхронных запросов.

Блоки Try и Catch могут использоваться только для синхронных блоков кода.Когда вы делаете вызов API, он асинхронный (т.е. занимает произвольное количество времени для завершения).Чтобы поймать ошибку в асинхронном блоке, вы обычно используете .catch (handlerFunction), прикрепленный к обещанию.

Это должно быть что-то вроде:

axios.post(myurl, mydata).then(res => console.log(res))
   .catch(e => console.log(e))

Так что getOffer может быть переписан:

const getOffers = (trequest) => {
    return axios(trequest)
      .catch(e => console.log(e) );
}

Чтобы получить результаты, вам нужно будет сделать что-то вроде:

getOffers('/getmyoffers').then(results => console.log(results) )

Редактировать - чтобы обновить состояние клиентов, вы можете сделать это:

getOffers('/getmyoffers').then(results => this.setState({customers:results.data} )
0 голосов
/ 11 марта 2019

Проблема в вашем getCustomerOffers методе. В этом методе вы устанавливаете состояние customers для обещания, которое вызывает повторное выполнение метода render, в этот момент this.state.customers больше не является массивом (вместо этого обещание).

Так что теперь, если вы понимаете основную причину, исправление будет простым, как кто-то уже опубликовал:

axios(trequest).then((response) => {
   this.setState({ customers: response.data });
}, e => {
   console.log(e);
});

Я настоятельно рекомендую прочитать больше о Javascript Asynchronous, так как это поможет вам в долгосрочной перспективе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...