useLazyQuery run after component rerender
Hi all.
I switch to new version of Apollo client. Actually v 3.3.6.
I use useLazyQuery in component with useQuery and useMutation. If I clicked on button,which open confirm window,then I call useLazyQuery function called load({variables:{id}}), query runs and give me a data. Thats right.But after run some mutation and query for new data from useQuery, than useLazyQuery runs again with same id. But load function is on handleClick, which not fire and this id is only from this handleClick.
And I dont know why. One difference is, new inMemoryCache. When I use this from package apollo-inmemory cache and not from @apollo/client than everything is allright.
Can you someone explain me, what I doing wrong or maybe bug in InMemoryCache?
Thans and sorry for my english :-)
Similar issue here. UseLazyQuery seems to send a request to the server everytime my component re-renders.
"@apollo/client": "^3.3.6",
"@apollo/react-hooks": "^3.1.3",
Same here
Also having this problem, fired lazyQuery, after it finishes, other queries run in sequence, some are even using old variables from previous calls. Seems to be a problem in cache handling, it works if I use the "no-cache" fetchPolicy.
Also having this problem, fired lazyQuery, after it finishes, other queries run in sequence, some are even using old variables from previous calls. Seems to be a problem in cache handling, it works if I use the "no-cache" fetchPolicy.
Yes same here. In my case, if I change fetchPolicy to "no-cache" and query runs, I have same old value. For example....I create a new request in form and then run fetch some query, network request will place, but in menu, where should change number from request, I have same old number.
I believe I am experiencing this same issue. I have a useLazyQuery with a fetch policy of network-only that, once it has been explicitly executed once by a user interaction, is making additional network requests over the wire whenever the component re-renders, even though the execute function, nor the refetch function, have been explicitly called.
After poking around a bit in useBaseQuery, it looks like a forceUpdate is getting triggered with an increase in the tick value even though none of the lazy query's variables are changing in the host component. I have confirmed this behavior by hardcoding the query variable values to primitives so that they always have referential equality. In that scenario, I would never expect a lazy query to re-execute unless explicitly asked to via the execute function or refetch.
I think we can use nextFetchPolicy: 'cache-first', as a workaround, just so network requests are avoided. But it is a bug a for sure
I am experiencing this as well, although, for some reason, only if the previous intended call of the lazy query returns an error. If the query resolves corretly and returns data, no follow up requests are made.
Also having the same issue. useLazyQuery re-runs the query on component re-render.
This issue is also happening to me and it seems a bug since the documentation states "The useLazyQuery hook is perfect for executing queries in response to events other than component rendering."
I have tried every type of fetchPolicy without any success (even though it does not feel right because it still creates a new network request), the requests are always re-executed on component render resulting in data going back to undefined and then to the new request request (onCompleted is always re-executed as well).
This totally invalidates the objective and usage of useLazyQuery.
same issue here
When does the 3.5 release go live? I have the same issue when using conditionally two different lazyQueries inside a useEffect when all lazyQueries have been executed previously whenever I call one of them the other one is being executed without being called, very weird.
@Pedro-Puga Are you confirming that this issue (or a separate issue you have) is fixed by 3.5? We’re planning on releasing 3.5 on the 27th, so if you’d like to try the beta by installing @apollo/client@beta, I would be eternally grateful!
@Pedro-Puga Are you confirming that this issue (or a separate issue you have) is fixed by 3.5? We’re planning on releasing 3.5 on the 27th, so if you’d like to try the beta by installing @apollo/client@beta, I would be eternally grateful!
No... my comment was before trying your beta, I'm sorry, I tried using the v3.5.0-beta.11 and the issue still persist, I can try to help you having a quick call next week to see exactly what my use case is and try to solve it, but this new beta version does not fix my issue.
I have also been having this problem but just discovered something that might be the cause. I have a React component that builds out the ApolloClient and creates all of its various links. I found that some of the links were not memoized and so were being rebuilt with each render, and also that I was incorrectly setting the dependencies for the useMemo hooks that created the links so that they would be regenerated way too often as well. Cleaning that up seems to have totally solved the problem for me. If you're having this problem, try memoizing everything and narrowing those dependencies as much as possible to reduce rebuilds of the client.
@aub ...setting the dependencies for the useMemo hooks...
I'm so sorry form my mistake (closing this issue ) . I'm very tired I guess :-) In my case, useMemo not used. That's not the problem.
I guess all I'm trying to say is that while I don't know exactly why the problem occurs, it does seem to be triggered in my case by frequently rebuilding the ApolloClient. I don't think useMemo specifically is the problem, but it can be a solution to the problem if used properly because it can cut down on those rebuilds.
Hey everyone!
I had a call with @Pedro-Puga last week about useLazyQuery() which gave me some insight into the problem people in this issue are facing. So one thing that might not be known is that once the useLazyQuery() hook begins executing, it behaves more or less exactly like useQuery(). So if you update the variables, or if you have polling, or do any sort of cache invalidation or updating, the query will run again. I know this is confusing but that’s the way this hook was designed. This is probably the thing people in this issue are struggling with. Think of the execution function as starting the query, not controlling exactly when the query runs.
As an alternative, you can use useQuery with the skip option to prevent the query from being run when you don’t want it to be run.
Another odd detail about useLazyQuery()’s design is that we don’t allow passing the skip option, even though the query now behaves like a normal query. I think we’ll probably add this to useLazyQuery() soon.
Wow, thanks for that explanation @brainkim! I think it'd be really helpful to add to the documentation for useLazyQuery. Even after reading your explanation, the way the documentation describes useLazyQuery suggests (to my mind) that the query will only be executed when you explicitly call the function it provides.
Hey everyone!
I had a call with @Pedro-Puga last week about
useLazyQuery()which gave me some insight into the problem people in this issue are facing. So one thing that might not be known is that once theuseLazyQuery()hook begins executing, it behaves more or less exactly likeuseQuery(). So if you update the variables, or if you have polling, or do any sort of cache invalidation or updating, the query will run again. I know this is confusing but that’s the way this hook was designed. This is probably the thing people in this issue are struggling with. Think of the execution function as starting the query, not controlling exactly when the query runs.As an alternative, you can use
useQuerywith theskipoption to prevent the query from being run when you don’t want it to be run.Another odd detail about
useLazyQuery()’s design is that we don’t allow passing theskipoption, even though the query now behaves like a normal query. I think we’ll probably add this touseLazyQuery()soon.
But in previous version of Apollo, this issue was not exist.In my case, this useLazyQuery is launched only with click the button and variable is handed over v onClick handler.And this variable are not changed.Is it primitive value. Your explanation does not make sense or I dont understand useLazyQuery. Another thing is Apollo cache. Which is horible.
@pronovaso - I think I had the same problem you described, which is why I found this issue. I'm not commenting as to whether this should be considered a bug or not. Instead I'll just provide the work-arounds that seem to resolve the issue for me. I am using Apollo Client v3.4.0, btw.
I found two techniques to prevent the useLazyQuery from firing automatically after my useMutation call updated the cache:
- Use the following fetch policies on the
useLazyQuery:
fetchPolicy: "network-only",
nextFetchPolicy: "cache-first",
That seems to work for me. (Previously I had it set up with fetchPolich: "cache-and-network" )
- Another option is to use the
onQueryUpdatedoption on myuseMutation:
onQueryUpdated: (observableQuery) => {
return observableQuery.queryName !== "LazyQueryName"
},
That seems to work too, but I don't like it as much as option 1 because it seems to rely too heavily on the query name which is otherwise pretty arbitrary.
Hopefully this helps you.
I totally agree with @pronovaso , this behaviour doesn't make sense with useLazyQuery. Moreover, this issue is not properly workarounded yet, apart from use useQuery instead with cumbersome "skip" logics... this issue has been open for an year now and I think it should be addressed ASAP...
I have to fully support @manuFL @pronovaso stance on this. The expected behaviour of useLazyQuery is that requests are entirely manual and under the control of the application logic and not automatic in any way. Persisting with this odd pattern of behaviour and ignoring such a significant bug for this long after it has been identified does not inspire confidence in the library in general.
Fully support @atomless , @manuFL @pronovaso and others.
Is there an update to this? I feel like I must be missing something here. I don't understand how something as widely adopted as Apollo Client does not have a simple way to only fetch data on user event, as opposed to fetching data automatically every time the component renders.
If you're just looking to fetch data once, I think you can do something like this:
const client = useApolloClient();
const someEventHandler = async () => {
const queryResult = await client.query({ ...queryOptions });
// do something with queryResult
};
FWIW, I've found that this seems to be fixed in the 3.6 beta builds. I was also having a problem where useLazyQuery would seem to skip the cache and that seems to be fixed as well. I wish I had some idea about the release schedule for that version, but they're getting pretty high up in the beta release numbers and have been releasing betas for 5 months.
Thanks for trying the betas @aub (and @dylanwulf and possibly others in this thread)! Those time windows would be shorter if more folks gave feedback (positive or negative) on the beta/RC releases.
The good news is that we're on @apollo/[email protected] right now, aiming to finalize the v3.6 release by the end of this week, as long as we don't find any new show-stopping bugs. Please try running npm i @apollo/client@beta when you have the chance, since we (believe we have) fixed multiple useLazyQuery bugs in the v3.6 release.
@benjamn FWIW I've been using 3.6 rc1 and it's working great while solving all of the issues I've had related to useLazyQuery
We still have this issue on @apollo/client: 3.6.6. We only use the refetch function from useLazyQuery (so that we can await and get back the result from the function call) and after the first refetch call with the proper variables it starts to send requests of the same GraphQL query but with an empty variable object.
A workaround we currently use is setting fetchPolicy: 'cache-only'.
I have also been having this problem but just discovered something that might be the cause. I have a React component that builds out the ApolloClient and creates all of its various links. I found that some of the links were not memoized and so were being rebuilt with each render, and also that I was incorrectly setting the dependencies for the
useMemohooks that created the links so that they would be regenerated way too often as well. Cleaning that up seems to have totally solved the problem for me. If you're having this problem, try memoizing everything and narrowing those dependencies as much as possible to reduce rebuilds of the client.
Sorry to revive this but would you mind providing an example? I seem to be bumping into something similar, but not quite sure how to tackle this.
@aub an example of the above would be very helpful, thanks