-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Infinite renders when using output of useQueries in useEffect dependency array #3049
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It was a tradeoff we had to do in 3.9.0. from #1775
What’s your use-case, because what you are in the example can be done without useEffect… I think you can also memoize the input as per #2991, but results will still come in gradually from your api so the effect will get called multiple times.. |
Oh I see, thanks for the clarification. Basically I would like to create a separate hook that takes a dynamic array as an argument, which is used to generate multiple urls and fetch data from those urls. Then the hook performs an expensive operation to reformat the data for consumption in a component. I can't really put the expensive logic into the hook body because then it will get called every time the component rerenders. Being able to put that expensive logic into a Do you have any ideas for how to get around this? |
I think what we would need to do is wrap the result creation in I think it would just mean changing this line: to:
as
Do you want to PR that, ideally with a test that checks for referential stability when a re-render occurs that doesn't change any input? until then, you might need to use-deep-compare-effect to get around the issue. that being said, I still wouldn't do it in an effect + local state, but with a useMemo, which is made to memoize expensive computations:
|
I tried what you said by memoizing It actually gives Are there any other variables in use-deep-compare-effect should help me get around this issue for now though. Thanks for suggesting that! |
yeah, sorry for the wrong direction. calculating the result depends on other factors as well, not just the options. If the fetch returns, we also need the new result. So this doesn't work.
👍 |
Thanks @TkDodo for working with me on this haha. Is there really no way that we could add referential stability to the |
the result is computed optimistically on every render so that we can give information ahead of time, so that we can e.g. go to FYI, in v4, we will change the useQueries api to allow for top-level options:
this will theoretically give us the option to allow for a top-level |
closing because I don't think we can improve this for now, and we have a workaround. |
What's the current status of this? I am running into the same issue with useEffect -> set state. Some times it works, some times it does not. I guess switching to useMemo will not make a difference? Actually I'd be fine with a few reruns, until all queries are fetched. Will there be a workaround in v4? |
@carstenblt why do you need useEffect + setState? It's often an anti-pattern. |
@TkDodo yes, so I learned. Hence my question if useMemo fixes this. I need to run code with all the combined queries. |
at least |
it will just ignore the const queries = useMemo(
() => inputs.map(makeQueryFromInput),
[inputs]
);
const queryResults = useQueries(queries);
const processedData = useMemo(
() => queryResults.map(processData),
[queryResults],
); The So my workaround is now: const processedData = useMemo(
() => queryResults.map(processData),
[...queryResults.map((qr) => qr.data)],
); |
I'd rather write like this
dataUpdatedAt is the timestamp for when the query most recently returned the status as "success". It will be updated on refetch. The use of reduce is with the assumption that the sum of all timestamps of query results would be unique. So, whenever a query is refetched or a new array of queries is fetched, the 'processData' will be re-processed again. Since the return value of 'reduce' is a 'scalar' type - in this case, it is a number type -, as long as the resulting number is the same, useMemo won't be re-rendered. |
https://tkdodo.eu/blog/react-query-render-optimizations#structural-sharing |
Any suggestions of how to handle this suituation when the number of |
Describe the bug
When using the output of
useQueries
in the dependency array of auseEffect
, the containing component will rerender infinitely. This bug seems to have been introduced inv3.9.0
and exists in all later versions.Please see the Codesandbox I created below and change the version of
react-query
from 3.8.3 to any later version.To Reproduce
Steps to reproduce the behavior:
react-query
version fromv3.8.3
tov3.9.0
or greater to see the issue. (Warning, might freeze your browser due to infinite rerenders)Expected behavior
Expect the results of
v3.8.3
and lower, where the useEffect is only called once when needed.Desktop (please complete the following information):
The text was updated successfully, but these errors were encountered: