Skip to content
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

Inconsistent cache result's when two or more component calls to useLazyQuery with the same query #7923

Open
DaniAcu opened this issue Mar 30, 2021 · 2 comments

Comments

@DaniAcu
Copy link

DaniAcu commented Mar 30, 2021

Intended outcome:
The cache should be shared between two instances of useLazyQuery that use the exact same parameters. If we create an abstraction of useLazyQuery each component that uses it should have the same expected behavior (fetching to graphql or returning cache results).

Abstraction sample

function useFetchBooks () {
   const [, setState] = useGlobalState();
   
   const [fetchBooks, { data, loading, error }] = useLazyQuery(SIMPLE_QUERY);
   
   useEffect(() => {
     if(loading || !data) return;
    
     setState({
       books: data.results
     })
   }, [data, loading])


  return React.useCallback(
    (varaibles) => {
      fetchBooks({
        variables
      });
    },
    [fetchBooks]
  );
}

Actual outcome:
If you use the abstraction into 2 components and show the store list into another component. You will have mismatched between the results. Every time that call to graphql will work but when you try to load the result from cached 2 times it will return all time the first

How to reproduce the issue:
Steps to reproduce it:

  • Insert a string into the first input and submit
  • Insert other string into the second input and submit
  • Submit the first input again
  • Submit the second input again

Codesandbox: https://codesandbox.io/s/uselazyqueryissue-forked-1wv4c?file=/src/App.jsx

I create a small store using React.Context and try to save on the store each result. And an effect to watch for data changes because onComplete doesn't dispatch on cache results

Versions

System:
    OS: Linux 4.4 Debian GNU/Linux 10 (buster) 10 (buster)
Binaries:
    Node: 12.18.2 - ~/.nvm/versions/node/v12.18.2/bin/node
    Yarn: 1.22.5 - /usr/bin/yarn
    npm: 6.14.8 - /usr/bin/npm
Browsers:
    Firefox: 78.5.0esr
npmPackages:
    @apollo/react-testing: 3.1.4 => 3.1.4 
    apollo-boost: 0.4.9 => 0.4.9 
    apollo-cache-inmemory: 1.6.6 => 1.6.6 
    apollo-link-batch-http: 1.2.14 => 1.2.14 
    apollo-link-timeout: 1.4.1 => 1.4.1 
    apollo-progressive-fragment-matcher: 1.0.8 => 1.0.8 
    react-apollo: 3.1.5 => 3.1.5 
@brainkim
Copy link
Contributor

brainkim commented Apr 12, 2021

Hi! Thank you for opening this issue, and thank you for providing a runnable code example.

Unfortunately, I’m having a bit of trouble wrapping my head around your code. Firstly, you’re writing an onSubmit handler but passing it as an onChange callback, which in essence causes the callback to fire whenever the user types, rather than when the form is submitted. Therefore, you’re actually causing a form submit and reloading the page whenever you click one of those buttons. Secondly, I’m having a little bit of difficulty attempting to understand what you intend to happen because the heavy usage of contexts. I count three contexts in the example alone, and not sure what passing around the setState/reducer functions via contexts is meant to accomplish.

Finally, can you rephrase this part:

If you use the abstraction into 2 components and show the store list into another component. You will have mismatched between the results. Every time that call to graphql will work but when you try to load the result from cached 2 times it will return all time the first

What do you expect to see on the screen? Do you want the queries to run independently? Do you expect the lists to be concatenated? I might need a little bit of help understanding this part, and am very sorry if I’m missing the point of your example 😓

As always, thanks for reaching out, and I’m happy to go back and forth until we figure this out. I’ll leave your code on my computer for now so I can jump back in and try things out when you get a chance to respond 😊

@brainkim brainkim added 🏓 awaiting-contributor-response requires input from a contributor and removed 🚧 in-triage Issue currently being triaged labels Apr 12, 2021
@DaniAcu
Copy link
Author

DaniAcu commented Apr 12, 2021

First of all, sorry. I played around with it to check how I can fixed in my proyect. Let me create a fork just with the error to prevent misunderstanding. https://codesandbox.io/s/uselazyqueryissue-forked-1wv4c?file=/src/App.jsx

In simple words, the issue is that the cache is not updating.
If you use the abstraction that I put abov into 2 component at the same level as the ActionSection and follow the steps. The last submit is dispatched but doesn't update the list (the data is not updating with the cache).

I was create other component and a hook (Wrapper and useApplyWrapper) that only put this on top of the tree and share the exactly same function to each component that case, solve the error.

Gif:
useLazyIssue

@brainkim brainkim removed the 🏓 awaiting-contributor-response requires input from a contributor label Apr 12, 2021
@hwillson hwillson added the 🔍 investigate Investigate further label May 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants