简体   繁体   English

在ReactJS中获取数据

[英]Fetch data in ReactJS

There is a get request in componentDidMount() componentDidMount()有一个获取请求

componentDidMount() {
   var manufacturers = []

   this.props.participants.map(participant => {
     Get("manufacturer/" + participant.id, "").then(result => {
      manufacturers.push(result)
      console.log(manufacturers)
    });
  });

  this.setState({
    participants: manufacturers
  })
}

This console.log(manufacturers) shows that there are objects in the array, but the state of component is empty. 这个console.log(manufacturers)显示数组中有对象,但是组件的状态为空。 How to set it properly after fetching data? 提取数据后如何正确设置?

Code of Get() function: Get()函数的代码:

const Config = require('Config')
export async function Get(type, userData) {
    let BaseURL = Config.serverUrl;
    let result = {};
    if(userData)
        result = await fetch(BaseURL+type, {
                method: 'GET',
                headers: new Headers({
                    'Authorization': 'Bearer ' + userData,
                    'Content-Type': 'application/json'
                })
        });
    else
        result = await fetch(BaseURL+type, {
            method: 'GET',
            headers: new Headers({
                'Content-Type': 'application/json'
            })
        });
    let data = await result.json();
    return data;
}

Since you have multiple Get calls to be made and each one is async , you will have to wait until all the result is collected and then set it to the state. 由于您要进行多个Get调用,并且每个调用都是async ,因此必须等待直到所有结果collected ,然后将其设置为state。 You can do it by using Promise.all which can wait for all the Get calls to be resolved first, and then set the data to the state. 您可以使用Promise.all来做到这一点,它可以先wait所有Get调用得到解析,然后再将数据设置为状态。

I would first create an async function and call it in componentDidMount . 我首先创建一个async函数,然后在componentDidMount调用它。

componentDidMount() {
  this.fetchAllData();
}

Then inside this method, wait for all Promises to be resolved and set it to the state once we have the data. 然后,在此方法中,等待所有Promises解析完毕,并在获得数据后将其设置为状态。 you might have to wrap the whole function inside a try..catch block so that if there is any promise rejection due to failure of network call, you can handle it appropriately. 您可能必须将整个函数包装在try..catch块中,以便在由于网络调用失败而导致拒绝任何诺言时,可以进行适当处理。

fetchAllData = async () => {
  const manufacturers = await Promise.all(
    this.props.participants.map(participant => 
      Get("manufacturer/" + participant.id, ""))
  )
  this.setState(manufacturers)
};

You need to setState in Get promise callback 您需要在Get promise回调中设置setState

componentDidMount() {
   var manufacturers = []

   this.props.participants.map(participant => {
     Get("manufacturer/" + participant.id, "").then(result => {
      manufacturers.push(result)
      console.log(manufacturers)
      this.setState({
        participants: manufacturers
      })
    });
  });
}

You should move your this.setState inside of the .then. 您应该将this.setState移到.then内。 Don't exactly know why you're pushing the data to the manufacturers array first. 不完全知道为什么要先将数据推送到厂商阵列。 If you use that array for something. 如果您将该阵列用于某些用途。 If you already have the result in the state you probably won't need the manufacturers array. 如果您已经有处于状态的结果,则可能不需要Manufacturers数组。 If not .. You can just set the state with the result like below: 如果不是..您可以使用如下结果设置状态:

componentDidMount() {
   var manufacturers = []

   this.props.participants.map(participant => {
     Get("manufacturer/" + participant.id, "").then(result => {
      manufacturers.push(result) // Do you need this?
      console.log(manufacturers)
        this.setState({
          participants: result
        })
    });
  });
}

The problem comes from async logic. 问题来自异步逻辑。 Using this.setState() outside of the fetch's then() causes the manufacturers property to be empty. 在提取的then() this.setState()外部使用this.setState()会导致manufacturers属性为空。

What is complex in your case is that you need to resolve multiple queries in parallel before updating the state. 您的情况很复杂,您需要在更新状态之前并行解析多个查询。 This can be made using the Promise.all() function : 这可以使用Promise.all()函数来实现:

componentDidMount() {
  Promise.all(this.props.participants.map(participant =>
    Get("manufacturer/" + participant.id, "")
  ).then(results => {
    this.setState({
      participants: results // or results.map(result => result.data()) ...
    })
 })
}

Initialize the state before the ComponentDidMount method is called: 在调用ComponentDidMount方法之前初始化状态:

constructor() {
    super();
    this.state = { participants:null }
}

you should always update State in 'then' or catch block of promise when promise is resolved/rejected...like below 您应始终在'then'中更新State或在诺言被解决/拒绝时捕获诺言块...如下所示

componentDidMount() {
var manufacturers = []

this.props.participants.map(participant => {
 Get("manufacturer/" + participant.id, "").then(result => {
  manufacturers.push(result);

   this.setState({participants: manufacturers});
   console.log(manufacturers);

  });
 });
}

Since your get function returns promise which is async call, when get function executes, it skips to next line of code before resolving to this.setState() in your case, hence not showing updated state. 由于您的get函数返回的承诺是异步调用,因此在执行get函数时,在您遇到的情况下,在解析为this.setState()之前,它会跳到下一行代码,因此不会显示更新状态。 Always remember setState() itself is async and if u need to do any operation after setState , do it in setState() 's callback optional argument like:- 永远记住setState()本身是异步的,如果您需要在setState之后执行任何操作,请在setState()的回调可选参数中进行操作,例如:

this.setState((currentState)=>{
 // you can access the currentState here
 },()=>{
 //your callback... here you can access directly this.state since it is guranteed 
  //that it will be updated state always
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM