I'm trying to use useLazyQuery hook, in a function component, and execute the query on button click. So, i'm using the "called" parameter alongside "loading" to check if my "Navigate to Google" button was pressed and the query was executed successfully to continue executing my desired action (in this case navigate to www.google.com).
On the first execution everything works as expected but when i'm executing another action in the same screen that triggers a re-render, the "called" parameter from the previous action is still "true" so my previous action is executed again even though i didn't pressed the "Navigate to Google" button again.
Here is my TestFunctionComponent. To reproduce the issue first press the "Navigate to Google" button and then press "Force re-render" button.
In my application i use the query to retrieve the link to navigate on button click.
const useForceUpdate = () => useState()[1];
const TestFunctionComponent = () => {
const forceUpdate = useForceUpdate()
const [executeQuery, { called, loading, data }] = useLazyQuery(MY_QUERY);
if (called && !loading) {
window.open(data .navigationLink, '_blank')
}
const handleOpenAnalysisFormPdf = () => {
return executeQuery({
variables: {
medicalDocumentId: 6089249
},
});
}
return (
<Fragment>
<Button variant="outlined" onClick={handleOpenAnalysisFormPdf}>
{"Navigate to Google"}
</Button>
<Button variant="outlined" onClick={forceUpdate}>
{"Force re-render"}
</Button>
</Fragment>
)
}
export default TestFunctionComponent;
Thank you!
I have a similar issue:
const [getSimilarProjects, { loading, data }] = useLazyQuery(SIMILAR_PROJECTS_QUERY, {
variables: {
id: project.id,
},
})
This one works:
const handleSimilarProjects = useCallback(() => {
getSimilarProjects()
}, [getSimilarProjects])
This one dosen't:
const handletoggleFollow = useCallback(() => {
getSimilarProjects()
toggleFollow({
variables: {
id: 123,
},
})
}, [getSimilarProjects, toggleFollow, project])
but if I use each mutation separate they work.
@pontusab This is not really my case, my problem is that after the first execution of the query was done successfully and this line window.open(data .navigationLink, '_blank')
is executed, on any other action executed on this screen that triggers a re-render, that windows.open
command is triggered again and again because called
parameter from my if statement is never false.
So, i'm using the "called" parameter alongside "loading" to check if my "Navigate to Google" button was pressed and the query was executed successfully to continue executing my desired action (in this case navigate to www.google.com).
If you provide an onCompleted
callback to useLazyQuery
if will be executed once your query completes successfully. See docs for options.
So, i'm using the "called" parameter alongside "loading" to check if my "Navigate to Google" button was pressed and the query was executed successfully to continue executing my desired action (in this case navigate to www.google.com).
If you provide an
onCompleted
callback touseLazyQuery
if will be executed once your query completes successfully. See docs for options.
I don't think this fixes the underlying issue. Unless the called
can be reset to false via an exposed method or setter, it's set once a single query is made, regardless of it's response.
My use case is to authenticate an input against a graphql endpoint, on "Submit" I invoke the query via useLazyQuery
, check if the response is successful and then navigate away or show an error. It would be good to be able to set called
to false until it's next called via useLazyQuery
.
I too have encountered this very same issue. The called
attribute is not reset on re-render. A workaround I've found that might be useful considering your scenario is to use useQuery
with the skip
parameter set to true
, in conjunction with the useEffect
hook to control what to do on a re-render. This way you can still call the refetch()
method, and the behavior will be similar to the one expected from a lazy query.
Most helpful comment
I don't think this fixes the underlying issue. Unless the
called
can be reset to false via an exposed method or setter, it's set once a single query is made, regardless of it's response.My use case is to authenticate an input against a graphql endpoint, on "Submit" I invoke the query via
useLazyQuery
, check if the response is successful and then navigate away or show an error. It would be good to be able to setcalled
to false until it's next called viauseLazyQuery
.