4 ms·
I would expect a bit more in-depth article from Martin Fowler website. The shown implementation is naive and prone to bugs, for example a race condition. If th
by morbicer 2y ago
I would expect a bit more in-depth article from Martin Fowler website.
The shown implementation is naive and prone to bugs, for example a race condition. If this id is rapidly changed (say from 1->2), and the first request arrives last, you think you are looking at user 2 but you've loaded data for user 1.
const [user, setUser] = useState<User | undefined>();
useEffect(() => {
const fetchUser = async () => {
const response = await fetch(`/api/users/${id}`);
const jsonData = await response.json();
setUser(jsonData);
};
fetchUser();
}, [id]);
If you don't know what you're doing, use Tanstack Query libs or read a better article.
- https://tanstack.com/query/latest https://tanstack.com/query/latest
- https://maxrozen.com/race-conditions-fetching-data-react-with-useeffect https://maxrozen.com/race-conditions-fetching-data-react-wit...
- yamumsahoe 2y agoour workaround on this is to use a fetch wrapper that resolves all similar requests to the same inflight requests. awful but works.
- _fat_santa 2y agoThese days unless a react app needs to do something really special, I always reach for and recommend others reach for Tanstack. Currently have a react frontend that's like 50k LOC and it's been chugging with Tanstack Query since day 1 and we have had zero regrets. It's truly one of the best React libraries out there right now.
- hu3 2y agoFor line of business applications, a quick 80/20 solution is putting a spinner blocking the screen when I click the [edit user 1 button].
- dspillett 2y agoIf you are going to block further activity, to be safe block future requests in code too (a check on the event handler that might make the request most likely) in case someone tries to automate the app via browser extension or bookmarklet. Just blocking clicks with a UI overlay doesn't always cut it. Or in case some fool on your dev team calls the events to automate (or for other reasons trigger) something that wasn't intended to be called that way, of course, though once you start defending against iffy practise from within you are fighting a battle you are going to lose!
- kitkat_new 2y agosounds more like 20/20 solution ux-wise better immediately hide user1 and show a loading button and use rxjs's switchmap
- hu3 2y agoHow would rxjs's switchmap prevent the user from clicking user2 button? Also your proposed solution involves a lot more moving pieces. Sounds like a 20/80 solution.
- kitkat_new 2y agoyou mean user1 button? It would throw away the previous http request and users 1 data wouldn't even show up Hiding the elements/div would prevent the user from clicking that button. I don't see how it is 20/80. Switchmap is just a different way of doing things, and hiding the deiv instead of blocking doesn't add really add more effort as well. So I don't see how it's a lot of effort while also missing a lot of the desired features?
- hu3 2y ago> Hiding the elements/div would prevent the user from clicking that button. If you're going to start adding logic to hide other elements conditionaly it's prone to become spaguetti. And how would that scale code-wise? Might as well dim the screen and show a loading spinner to convey to the user that they should wait, a fraction of a second on average. Remember this is in the context of a LOB app. Not facbook. Just show a loading spinner from an axios callback and be done with it. It's so fast anyway.
- sabbaticaldev 2y agowhy axios? JS has native fetch everywhere for ages. let’s remove the moving pieces.
- hu3 2y ago
- Rapzid 2y agoAlso useEffect callback is run after the component mounts. I often use memo when kicking off async processes on component mount.
- madeofpalk 2y agoAs in useMemo to make API calls? That is definitely not correct. React explicitly makes no guarantees about how infrequently the fn is called or how long the value is cached for.
- Rapzid 2y agoIt doesn't matter for 99.9% of use cases how long React caches it if your using it to debounce read requests.
- madeofpalk 2y agoSure, if you're using it to memoize a calculation. But triggering an api request having side effects is 100% incorrect.
- Rapzid 2y agoWhy?
- donjoe 2y agoUseMemo should not be used for fetching/kicking off a fetch either. UseMemo fans should be pure. Using logic that belongs into useEffect (logic that happens _outside_ the reactive flow) could potentially lead to other side effects which are very hard to debug. Just a example: a lot of fetch implementations are using fetch with a cache triggered in useMemo returning immediately. You will probably have a setState somewhere in the flow which will terribly interrupt react and break your page. In case you trigger a native fetch, you've got no way to cancel the call due to the missing cleanup fn.
- 2y ago