React Query - Slow performance with many small cached requests
I have a list of accordions. Every accordion have items that contain image.
On accordion click, I fetch items text data and image id to speed up list loading and load images later.
Inside an item, I use image id to fetch an image per item. Image is in base64 format.
In every accordion, I can have 10 or more items, so in total there can be few hundreds.
When I open just one or two accordions and cache them, the app is working fine. CPU jumps to 20-30%.
But if I open a lot of accordions and cache them (I can close them), next time I open accordion CPU usage jumps to 100%.
List still works fluent - it displays data instantly, however if at this moment go to diffrent view in my app, request from this view will not be fetched for like few seconds.
My guess is that react is rendering fine but when there are a lot of requested cached in react query than it checks them all to see if they need update or not. While cached is checked, new request (not cached ones) are blocked.
This happens even if staleTime is infinite.
If there is a way to optimize react query, that would be great.
If not, I will probably try to counter this with by fetching images per accordion to make number of react query entries in cache smaller.
7 Replies
I recommend using React Query Devtools, React Devtools & your browser's profiler to see what's actually going on. It's hard to say anything concrete on this basis.
There are 3s of 15ms long checkIfSnapshotChanged functions calls in performance tab.
In React profiler, there are plenty of: QueryRow key =[] which correspond to react query keys.
I just noticed that those QueryRow key =[] are under ReactQueryDevtools.
So I disabled devtools and now I hit max 20% on CPU.
Seems that my CPU was spending all power on updating hidden devtools view.
You can see on the screenshot that devtools takes 80% of time to render.
If you used URLs to images and the images live on a CDN so the browser can load and cache them separately. I wouldn't encode images into base64 strings in an API call for react query to cache.
I know that having just URLs for images instead of base64 would be much better and easier, but unfortunately, frontend doesn't have permissions to image's storage in my project right now.
This is not a public app, so maybe this is the correct security approach, but if not let me know.
I would have 2 image services a prod one that you care about and a dev/Integration one that you don't lax permissions etc and develop with the non prod one so just use env vars to know which one is which all you need is a place to dump the file and an returned URL S3 storage is cheap you could leave stuff there forever. Then you can keep your API res data trim and slim.
You can use next config for a permanent redirect for anything /images/....blah.png to point at the cloudfront for the S3 bucket
Just so you know I was using "@tanstack/react-query-devtools": "^4.0.10", after I updated to current newest "@tanstack/react-query-devtools": "^4.24.10" it is working much better with devtools enabled. However, it still suffers the same performance issues when opened. So it seems there was a bug that when devtools were hidden it was still rendered as if there were opened.