I’m learning React and can’t understand how to properly use async functions inside of the components
I want to create a test component that:
- Receives a list of requests to be sent
- Executes them one by one (in async function)
- When the response is received, it appends it to the list of responses
- If all requests were successful automatically shows a modal
- If any request fails, shows a button that the user needs to click in order to show modal
Right now I managed to do this
function requestReportReducer(state, action) {
switch (action.type) {
case 'append':
return [...state, action.payload]
}
}
export default function RequestList(props) {
const [report, reduceReport] = useReducer(requestReportReducer, [])
const [hasErrors, setHasErrors] = useState(false)
useEffect(() => {
async function sendRequests() {
for (const requestData of Object.values(props.requests)) {
const response = await sendRequest()
const isSuccessful = response.statusCode < 400
reduceReport({
type: 'append', payload: {
isSuccessful: isSuccessful,
responseCode: response.statusCode,
responseBody: response.body,
}
})
if (!isSuccessful)
setHasErrors(true)
}
if (!hasErrors)
showAllRequestsAreSentModal()
}
sendRequests()
}, [])
return (
<div>
<dl>
{report && report.map((requestReport: RequestReport) => (
<p>some html here</p>
))}
</dl>
{hasErrors && <button onClick={showAllRequestsAreSentModal}>Finish execution</button>}
</div>
)
}
As you can see, I want to be able to set hasErrors
var and read it in both the async function and JSX which does not seem to work. I understand that this implementation is incorrect, but how can I fix it? I have found a lot of similar questions, but could not understand how to apply the suggestions proposed there in my case.
3
Answers
When you call
setHasErrors(true)
inside the loop, it will not immediately updatehasErrors
. You can use theuseEffect
hook to watch for changes inhasErrors
and trigger the modal accordingly.If you’re just learning react, it’s fine to code stuff like this yourself.
For real-work projects, I highly recommend using a wrapper around Promises.
@tanstack/react-query
is my personal (an many other’s) go-to solution.You’re facing this issue because it doesn’t immediately update the hasErrors variable in the outer scope , for solving this issue you can use the useEffect dependency array and update hasErrors using setHasErrors within the useEffect.