React中利用Promise控制isLoading状态并优化API请求逻辑咨询
Got it, let's work through this together. You want to properly handle the isLoading state alongside optimizing those parallel API requests in componentDidMount—here's a clean, efficient solution that hits both requirements.
First: Set Up Your Initial State
Start by making sure your component's state includes the isLoading flag. Based on typical UI patterns (and your stated goal), we'll set isLoading to true when we kick off the API calls, then flip it to false once both requests wrap up (success or failure).
state = { recentTransactionsRecipient: null, recentTransactionsSender: null, isLoading: false, };
Second: Refactor componentDidMount with Promise.all
Instead of firing two separate requests with independent .then() handlers, using Promise.all lets us run them in parallel—this is faster, and makes it way easier to manage the loading state once all operations finish.
Here's the updated code:
componentDidMount() { // Flip loading to true as soon as we start fetching data this.setState({ isLoading: true }); // Create our two API request promises, with error handling to avoid breaking the chain const getRecipientTransactions = this.Auth.recentTransactionsRecipient(this.props.id) .catch(() => null); // Return null on error so Promise.all doesn't fail entirely const getSenderTransactions = this.Auth.recentTransactionsSender(this.props.id) .catch(() => null); // Wait for both promises to resolve before updating state Promise.all([getRecipientTransactions, getSenderTransactions]) .then(([recipientResults, senderResults]) => { // Batch state updates for better performance this.setState({ recentTransactionsRecipient: recipientResults || null, recentTransactionsSender: senderResults || null, isLoading: false, // Turn off loading once all data is fetched }); }) .catch(() => { // Just in case something unexpected goes wrong with Promise.all, still turn off loading this.setState({ isLoading: false }); }); }
Quick Breakdown of Key Changes:
- Parallel Requests:
Promise.allruns both API calls at the same time instead of one after the other, cutting down on total load time. - Loading State Control: We set
isLoadingtotrueimmediately when starting the requests, so your UI can show a loading spinner or placeholder while data is being fetched. Once both requests are done (even if one fails), we turn loading off. - Robust Error Handling: Adding
.catch(() => null)to each individual promise ensures that a failure in one request doesn't crash the entire operation. The component will just set that specific state tonulland keep going. - Batched State Updates: We update all state properties in a single
setStatecall, which is more efficient than separate updates and avoids unnecessary re-renders.
If your original requirement was specifically to set isLoading to true only when both recentTransactionsRecipient and recentTransactionsSender have non-null values (which is a bit unusual for loading states), you can adjust the state update logic like this:
.then(([recipientResults, senderResults]) => { const recipientData = recipientResults || null; const senderData = senderResults || null; this.setState({ recentTransactionsRecipient: recipientData, recentTransactionsSender: senderData, isLoading: recipientData !== null && senderData !== null, }); })
But in most real-world cases, the first approach (showing loading while requests are in flight) is what users expect and need for a smooth UI experience.
内容的提问来源于stack exchange,提问作者ReactRouter4

