Реагируйте setState на массив, затем console.log (массив) возвращает заполненный массив объектов, но console.log (array.length) равен 0 - PullRequest
0 голосов
/ 09 января 2019

, поэтому я выбираю некоторые данные из двух URL-адресов по порядку и сохраняю ответные данные в массив, а затем устанавливаю состояние этого массива. Когда я console.log (dataArray), я могу видеть содержимое, но console.log (dataArray.length) равен 0, независимо от того, проверяю я это сразу после оператора setState или в методе render. Что я должен сделать, чтобы установить состояние для массива, прежде чем он будет отображаться снова? Спасибо !!!

   class App extends Component {
       state={
               dataArray:[]
           };

     componentDidMount(){

         this.getTrainInfo();
     }

     getTrainInfo=()=>{
             let arr=[];
             let data={};
      fetch('https://api-v3.mbta.com/predictions?filter[stop]=South+Station,North+Station&filter[direction_id]=0&include=vehicle&sort=departure_time')
             .then(response=>response.json())
             .then(res=> {

                 res.data.map(dat => {
                     data.departureTime = dat.attributes.departure_time;
                     data.boardingStaus = dat.attributes.status;
                     data.trainID = dat.relationships.route.data.id;
                     return data;
                 })
                   .forEach(data=>{
                fetch('https://api-v3.mbta.com/routes/' + data.trainID)
                         .then(response2 => response2.json())
                         .then(res2 => {
         data.destination = res2.data.attributes.direction_destinations[0];
                             arr.push(data);
                             //setState here work, but set too many times
                             //this.setState({dataArray:arr}) 
                          })
                     });
             })
             .then( ()=>{
                 this.setState({dataArray:arr});
      console.log(this.state.dataArray); //log an array full of objects.
      console.log(this.state.dataArray.length);  //but here length is 0.
             })
      };

     render() {
         let data=this.state.dataArray;
         let departureTime;
         let boardingStatus;
         let TrackNo;
         let destination;
         console.log(data); //log the array full of objects.
         console.log(data.length);  //but here the length is 0.
       if(data.length){
        departureTime=new Date(data[0].departureTime).toLocaleString('en-US',{hour:'numeric',minute:'numeric', hour12:true});
        boardingStatus= data[0].boardingStaus;
        TrackNo=(data[0].trackNo)?data[0].trackNo:0;
        destination=data[0].destination;
       }

       return (
         <div className="App">
             <h1>Train info</h1>
             <h2>{departureTime}
                 {boardingStatus}
                 {TrackNo}
                 {destination}
             </h2>

         </div>
       );
     }
   }

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Большое спасибо @aseferov !!! получается, что я должен использовать Promise.all (), чтобы setState обновил весь массив после завершения всех выборок.

        getTrainInfo=()=>{
             let arr=[];
             let data={};
         fetch('https://api-v3.mbta.com/predictions?filter[stop]=South+Station&filter[direction_id]=0&include=vehicle&sort=departure_time')
             .then(response=>response.json())
             .then(res=> {
                let changes= res.data.map(dat => {
                     data.departureTime = dat.attributes.departure_time;
                     data.trackNo=res.data[0].relationships.vehicle.data.id? res.data[0].relationships.vehicle.data.id:0;
                     data.boardingStaus = dat.attributes.status;
                     data.trainID = dat.relationships.route.data.id;
                     return 'https://api-v3.mbta.com/routes/' + data.trainID
                 });
                //let changes=['https://api-v3.mbta.com/routes/CR-Franklin','https://api-v3.mbta.com/routes/Red','https://api-v3.mbta.com/routes/Orange','https://api-v3.mbta.com/routes/Mattapan']
                 //console.log(changes); //an array of  urls
                 let requests=changes.map(change=>{return fetch(change).then(response=>response.json()).then(res=> res.data)});  //.then(response=>response.json()).then(res=> res.data)
                 //console.log(requests);
                 Promise.all(requests)
                     .then(responses=>responses.forEach(response=>{
                         console.log(response);  //returns Objects: res.data[0], res.data[1],...
                         let destination=response.attributes.direction_destinations[0];
                         data.destination=destination;
                         arr.push(data);
                     }))
                     .then(()=>{console.log(arr); this.setState({dataArray:arr}); })
             })
     };
0 голосов
/ 09 января 2019

Эта часть вашего кода выполняется до того, как ваши запросы выполняются внутри функции forEach, поэтому arr может быть пустым здесь

then( ()=>{
      this.setState({dataArray:arr});
      console.log(this.state.dataArray); //log an array full of objects.
      console.log(this.state.dataArray.length);  //but here length is 0.
})

Вы можете использовать prmoise.all для этой цели

getTrainInfo=()=>{
    let arr=[];
    let data={};
    fetch('https://api-v3.mbta.com/predictions?filter[stop]=South+Station,North+Station&filter[direction_id]=0&include=vehicle&sort=departure_time')
        .then(response=>response.json())
        .then(res=> {

            let changes = res.data.map(dat => {
                data.departureTime = dat.attributes.departure_time;
                data.boardingStaus = dat.attributes.status;
                data.trainID = dat.relationships.route.data.id;
                return data;
            });

            let requests = changes.forEach(data=>{
                    return fetch('https://api-v3.mbta.com/routes/' + data.trainID)
                        .then(response2 => response2.json())
                        .then(res2 => {
                            data.destination = res2.data.attributes.direction_destinations[0];
                            arr.push(data);
                            return res2
                        })
                });

            Promise.all(requests).then((values) => {
                this.setState({dataArray:arr});
            });

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