如何在componentDidMount React中进一步完成之前完全完成获取数据并将其分配给组件状态? [英] How to finish Fetch data completely and assign it to component state before proceeding further in componentDidMount React?

查看:54
本文介绍了如何在componentDidMount React中进一步完成之前完全完成获取数据并将其分配给组件状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须执行多个提取查询.根据我的第一个查询,我必须在收到所有i后再进行多个其他查询,我应该能够将数据分配给react组件状态.看来我是在fetch方法完成之前将值分配给组件状态,因此它们显示为空数组.

I have to perform multiple fetch queries. Based on my first query i have make to make a multiple other queries after receiving all the i should be able to assign the data to the react component state. It appears that i am assigning the values to the component state before the fetch method is finished and hence they appear empty array.

我尝试过从外部移除内部获取方法并执行查询.

I have tried by removing the inner fetch method outside and performing the query.

import React, { Component } from 'react';
import './App.css';
import Sensors from './iot/Sensors';

class App extends Component {
  constructor (props) {
      super (props);
      this.state = {
        status: 'disconnected',
        devices: [],
        dataPoints: []
      };
  }

  componentDidMount() {
    // Get Zigbee devices
    fetch('http://localhost:3000/ssapi/zb/dev')
    .then((res) => res.json())
    .then((data) => {

      this.setState({
        devices : data
       })
      data.map((device) => {
        const dataPoint = []
        JSON.parse(device.metadata).dataGroups.map((datagroup) =>{
          const url = 'http://localhost:3000/ssapi/zb/dev/' + device.id + '/ldev/' +  datagroup.ldevKey + '/data/' + datagroup.dpKey;
          fetch(url)
          .then((res) => res.json())
          .then((data) =>{
            dataPoint.concat(data)
            console.log('Data', data);
            console.log('Inside dataPoint', dataPoint);
          })
          .catch((error) => console.log(error));
        }) // dataGroups.map
        console.log("Final dataPoint", dataPoint);
        const dataPoints = this.state.dataPoints.concat(dataPoint);
        this.setState({ dataPoints });
      }) // data.map

    }) // fetch
    .catch((error) => console.log(error));
  }

  render() {
    console.log('Render Devices', this.state.devices);
    console.log('Render dataPoints', this.state.dataPoints);
  }][1]][1]

我希望最终组件的状态看起来像这样 或在渲染功能中-控制台日志记录应如下所示.

I am expecting a final component states that look like this or in render function - console logging should look like this.

devices = [{},{},{},{},{}...]
dataPoints = [[{},{},{},..], [{},{},{},..], [{},{},{},..], ....]

推荐答案

映射中的代码const dataPoints = this.state.dataPoints.concat(dataPoint)始终会连接空数组,因为fetch是异步的,您的dataPoint仅在api调用后会得到值.

your code const dataPoints = this.state.dataPoints.concat(dataPoint) inside map will always concat empty array, because fetch is asynchronus and your dataPoint will only get value after api calls.

其他问题是dataPoint.concat(data) concat返回一个新数组,但是您没有存储可以使用dataPoint = dataPoint.concat(data)dataPoint = [...dataPoint, ...data]

Other issue is dataPoint.concat(data) concat returns a new array but you are not storing the new array you can use dataPoint = dataPoint.concat(data) or dataPoint = [...dataPoint, ...data]

您需要在const dataPoints = this.state.dataPoints.concat(dataPoint)之前等待api调用的结果.您可以使用Promise.all

You need to wait for the result of api calls before const dataPoints = this.state.dataPoints.concat(dataPoint). You can use Promise.all

import React, { Component } from 'react';
import './App.css';
import Sensors from './iot/Sensors';

class App extends Component {
    constructor (props) {
    super (props);
    this.state = {
        status: 'disconnected',
        devices: [],
        dataPoints: []
    };
}

componentDidMount() {
    // Get Zigbee devices
    fetch('http://localhost:3000/ssapi/zb/dev')
    .then((res) => res.json())
    .then((data) => {
        this.setState({
            devices : data
        })
        //Using forEach instead of map because we don't need the return of map
        data.forEach((device) => {
            const urls = JSON.parse(device.metadata).dataGroups.map((datagroup) =>
                'http://localhost:3000/ssapi/zb/dev/' + device.id + '/ldev/' +  datagroup.ldevKey + '/data/' + datagroup.dpKey) // dataGroups.map
            Promise.all(urls.map(fetch))
            .then(responses => 
                Promise.all(responses.map(res => res.json()))
            )
            .then((data) =>{
                //This data will be array of responses of all fetch fired
                //destructuring response in array
                const dataPoint = data.reduce((acc, curr)=> acc.concat(curr),[]) 
                const dataPoints = this.state.dataPoints.concat(dataPoint)              
                console.log('All Data', data);
                console.log('Inside dataPoint', dataPoint);
                this.setState({ dataPoints });
            })
            .catch((error) => console.log(error));
        }) // data.map
    }) // fetch
    .catch((error) => console.log(error));
}

render() {
    console.log('Render Devices', this.state.devices);
    console.log('Render dataPoints', this.state.dataPoints);
}

这篇关于如何在componentDidMount React中进一步完成之前完全完成获取数据并将其分配给组件状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆