如何在axios响应之后使React中的setState同步

问题描述 投票:1回答:3

我使用axios发出HTTP请求,然后我在其中发出另一个HTTP请求,以便添加有关我获得的项目的一些细节。我将它推送到'orders'数组后我需要setState,但它之前就这样做了所以我不能以正确的方式打印它。它适用于SetTimeout但我想以更专业的方式做到这一点。我怎么能同步?

fetchOrders(){
    let orders = [];
    let status;
    this.setState({loading:true});
    http.get('/api/amazon/orders')
        .then(response => {
            if (response.status === 200) status = 200;
            orders = response.data;
            orders.map(order => {
                order.SellerSKU = "";
                http.get(`/api/amazon/orders/items/${order.AmazonOrderId}`)
                    .then(res => {
                        order.SellerSKU = res.data[0].SellerSKU;
                    })
                    .catch(error => {
                        console.log(error);
                    })    
            });
            setTimeout( () => {
                this.setState({orders, error: status ? false : true, loading:false})
            }, 1000);
        })
        .catch(error => {
            this.setState({loading:false, error:true});
            console.error(error);
        });
}
javascript reactjs asynchronous axios setstate
3个回答
2
投票

你似乎在问错误的问题,即如何实现异步同步,而你真的试图推迟设置你的状态,直到一切都完成。 (又名XY Problem

你不需要使setState同步 - 你只需要利用一些promise chaining和Promise.all,这将允许你推迟setState调用,直到一切都完成。

简而言之,您应该能够根据需要对此进行调整,并对响应应用更多转换:

fetchOrders() {
    http.get('/first')
        .then(r => r.data)
        .then(orders => {
            // This wraps the iterable of promises into another promise
            // that doesn't resolve until all the promises in the iterable
            // have finished.
            return Promise.all(orders.map((order) => http.get(`/second/${order.id}`).then(/* transform */))
        })
        .then(transformedOrderPromises => this.setState({ ... }); 
}

1
投票

setState可以采用回调函数,在完成mutate状态之后它将执行回调。所以你可以setState并在回调中添加你的第二个API调用。

像这样的东西:

http.get('/api/amazon/orders')
    .then(response => {
        if (response.status === 200) status = 200;
        orders = response.data;
        this.setState({orders, error: status ? false : true, loading:false}, 
          () => {
            orders.map(order => {
              order.SellerSKU = "";
              http.get(`/api/amazon/orders/items/${order.AmazonOrderId}`)
                  .then(res => {
                    order.SellerSKU = res.data[0].SellerSKU;
                  }).catch(error => {
                    console.log(error);
                  })    
        });
    })

请注意,我刚刚编辑了一个脏的方法,可能需要进行一些调整才能使其正常工作。


-3
投票

在我的项目中,我伪造了一个同步的setState以避免很多陷阱,使代码更清晰。这是我做的:

class MyComponent extends React.Component {
   // override react's setState
   setState(partialState) {
      const mergedState = { ...this.state, ...partialState };
      this.state = mergedState;
      super.setState(partialState);
   }
}

解释:在调用真正的setState之前,状态也设置为this.state,以便在实际更新之前对它的任何引用都是正确的。

唯一的缺点是你必须从MyComponent而不是React.Component延伸。

© www.soinside.com 2019 - 2024. All rights reserved.