The React useEffect hook is great for performing side effects in functional components. One common example of this is fetching data. If you're not ...
For further actions, you may consider blocking this person and/or reporting abuse
Great article. Thanks for the writing, Nick!
It's also a good idea to abort related HTTP requests when canceling.
You can implement it using AbortController and AbortSignal if you're using Fetch API, and XMLHttpRequest#abort if you're using XMLHttpRequest.
One issue that I think is still present in the code is the fact that every tab click is kicking off a new fetch. Instead of only storing the result of a single fetch, you might consider instead saving the results of all (or a subset of all) requests that have completed, and use the currently selected person/tab to index the list of fetched data. I’m more familiar with Vue than React, but the following is a stab at this (untested):
This has the added benefit that your navigation state is better decoupled from your object state, meaning that clicking around in your application doesn’t have the potential to leave your data in an inconsistent state if it gets more complicated.
It sounds like this concern would be more appropriately managed through cache headers from the backend. In this implementation, it seems the frontend is deciding that the initial data fetch is good for as long as the app is open.
It is a perfect point.
If we ignore it for a moment please, then my question is, is it possible to leverage
useMemo
hook for caching data in the example? How will that work?This was popping up on my feed and I wanted to share my higher-level abstraction I built using a generator function API.
If you have many
useEffect
hook usages or complexuseEffect
logic, all the checking on whether the task should be canceled can become quite tedious.Sample Usage:
In case the effect is canceled (due to unmount or dependency array change), the Promise that was
yield
-ed will be ignored and the generator won't be invoked with the resolved value.The API also allows registering optional cancelation handlers, which is quite handy for canceling in-flight requests.
The library can be found here: github.com/n1ru4l/use-async-effect and I also wrote a blog article about it: dev.to/n1ru4l/homebrew-react-hooks...
I am currently also designing an API for the V2 which will also support Node.js style callbacks beside promises.
I hope it can help some of you ☺️
Hi @nas5w . Thanks for writing this article. Great use of the
useEffect
cleaner.I think another way to resolve this issue is to keep the buttons disabled until the promise is resolved or rejected. This will make for a less confusing UX. User will not be able to click the conflicting buttons to being with.
Thanks! I think in this example, however, you wouldn’t want to prevent someone from navigating to another user’s profile just because a fetch request hasn’t returned. The user should be able to freely navigate the application regardless of whether the fetch request has resolved.
I'd also recommend using AbortController so that the fetch request is actually cancelled!
Does not work for components that fetch based on props.
But using the AbortController object makes it work as intended.
It's not a race condition, as here, and in React, is nothing about threads.
Reusing such phrases in the wrong context – investment for making people to understand things in messed way.
Moreover, the expression was coined by David A. Huffman in the area of logic circuits, so it would also be historically irrelevant to restrict its meaning to multithreading.
Source: en.wikipedia.org/wiki/Race_condition
Right! Thanks for the link :)
Why would you not call this a race condition? Why would race conditions not occur in an event loop environment?
I have heard some people make the argument that race conditions can only happen in multithreaded environments by definition. I don’t really agree (or think it matters) as you’ll find plenty of people out there who would contend that multithreading is not required to be a race condition. At any rate, I’m not terribly interested in calling it a “condition in which there is a race” just to avoid what some might consider a reserved phrase.
What about wrapping the fetch request with debounce function?