useLazyQuery is returning undefined in specific scenario

Hi, I am using useLazyQuery in a useEffect and I noticed a weird behavior which I am not sure if its intentional or not.

I have a schema that requires me to pass a valid string in order to be executed.

I defined my query handle like this

const [getProject,{ data: projectData, variables, called, error }] = useLazyQuery(query);

If I do the following, I get an error (which is fine):

    useEffect(() => {
        getProject({ variables: {
            _id: ""
        }})
    },[]);

   console.log(projectData, variables, called, error);

If I do this, I get the result of the 2nd query and the 1st one does not return an error:
This isn’t intentional, it was just for testing purposes.


    useEffect(() => {
        getProject({ variables: {
            _id: ""
        }})

        getProject({ variables: {
            _id: "60e3213dc0f730137ba8f1b6"
        }})                
    },[]);

   console.log(projectData, variables, called, error);

The third one, is where I get a weird result, I have the following code which receives an _id and fetches the data, on the first render, the data is an empty string, but the 2nd render (subsequent and instant), it has a value, but data returned is always undefined. The only way I found to fix it, was to add an if condition to make sure the _id given is not empty before executing the getProject. But I don’t understand why it didn’t return any error to indicate why it failed at all.


    useEffect(() => {
        getProject({ variables: {
            _id: props._id
        }})
    },[props._id]);

   console.log(projectData, variables, called, error);

I was simply wondering why it behave like this and if it was intentional or a bug.

I hope I was being clear enough.

Thanks!

Why are you using a lazy query when you seem to be calling it before the value is initialized?

Normally lazy queries are meant for specifying particular logic before making the query; it’s a contract of “I’ll do it when I’m ready”. if you’re trying to make the query before you’re ready, then that sounds like you need more work on “getting ready” or should use useQuery.

Not my code, so I could be misinterpreting.

I agree with your reasoning, that is why I added an if condition to make sure the _id was there before firing and it works great now.

I was simply wondering why it didn’t fail / return and error when it was firing once when _id was empty and again when it was ready. Because when I interpret it, the initial query should fail / return an error and the 2nd one should return the result, but in my test both return undefined with no errors.

Does #1 complete?

I assume it should return { data: { project: null} } or { data: null, errors: [...] }

If the whole query on #1 gives you undefined then it’s probably being canceled or something when #2 immediately overrides it, giving undefined because you didn’t give it time to finish with either a success or an error.

Seems like you’re stopping the HTTP request entirely. More realistically, I wouldn’t do it at all if I could help it, because using a lazy query, and then ignoring it before it can run doesn’t seem like a valid use case, and I’m not confident you’d even see someone write a test for such an edge case.

To me, it seems like you’re testing behavior that nobody would ever want, so nobody really knows what happens in that case as it pertains to a contractual guarantee because it’s not part of the contract of the API.

Ok from what I see this is what’s happening, when the _id is empty for the first example, called is true and networkStatus is loading.

For the last example with the props._id it being empty at first and then re-rendering with a value, if I do not add my if condition that checks to make sure to only run when it has a value, both queries have called as true and networkStatus as loading so it never completes at all. I noticed that in the network logs, only the initial render is sent but the 2nd render isn’t sent at all.

This is what I see based on those tests.
I just found it weird that in the 3rd example, the 2nd query does not fire at all.

Thanks for your input though.

Ah, sorry I was mostly looking at your 2nd example. You’ve got 3 examples with multiple calls in each, so I got confused and thought #2 meant example #2, not call #2 of example #3.

My gut tells me that the 2nd request in #3 would not being request by the browser maybe because of a “race” in JS around the promises, or the state isn’t being updated and useEffect is only happening once.

Weird territory, sorry. What does logging the _id in the effect show? Do you see two logs?

No problem!

Yes, I see multiple console logs because of the re-renders but related to the data, I see 2 console logs.
One for the 1st call of the #3 example, and another for the 2nd call.
That’s why I thought it was weird. But I know I just need to validate to make sure its not empty before calling.

It was just difficult to debug, as error returned by the useLazyQuery was undefined but in the network request I could see a network error which is ok for me.