apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.35k stars 2.66k forks source link

Bug when using lazyQuery and recoil #8304

Closed otwm closed 3 years ago

otwm commented 3 years ago

Intended outcome: In lazyQuery, it works only when the function is called exactly.

Actual outcome: When using lazyQuery, the query works once, and then the next execution, even without actually executing the query. This appears when using 'recoil' together. Details are explained with examples in the reproduction section below.

How to reproduce the issue:

// component A
const compA = () => {
    const myValue = useRecoilValue(myAtom)
    const [executeSome1Lazy, { data }] = useSome1LazyQuery({
       variables: { v: myValue.id } 
    })
    useEffect(() => {
       if (myValue.open && myValue.type === 'type-one') {
          console.log('execute some1')
          executeSome1Lazy()
       }
    }, [myValue.open])
}

// component B
const compB = () => {
    const myValue = useRecoilValue(myAtom)
    const [executeSome2Lazy, { data }] = useSome2LazyQuery({
        variables: { v: myValue.id } 
    })
    useEffect(() => {
       if (myValue.open && myValue.type === 'type-two') {
          console.log('execute some1')
          executeSome2Lazy()
       }
    }, [myValue.open])    
}

When you have the above code,

  1. Assign myAtom open to true and type to'type-one'.
  2. Initialize open of myAtom to false and type to null.
  3. Assign myAtom open to true and type to'type-two'.

If you proceed with the above procedure, executeSome1Lazy in step 3 is executed even if the condition is not met in the function in useEffect. To be precise, when useSome1LazyQuery is executed, it seems to be executed.

As a result of debugging, useDeepMemo in useBaseQuery is executed, and the result In QueryData's executeLazy function, runLazy is set to true, and as a result, it was confirmed that the query was executed unintentionally.

I'm not sure, but I guess carefully if the current method wasn't designed to take into account when used with 'recoil'.

Versions 3.2.2

otwm commented 3 years ago

I found the cause... This is not a bug. This was what happened with useDeepMemo working as the parameters changed due to recoil. If possible, assigning a variable at the moment of execution would prevent this from happening. Close the issue.