urql-graphql / urql

The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
https://urql.dev/goto/docs
MIT License
8.61k stars 449 forks source link

offline: `teardown` operations are called immediately on the page reload even if a `cache-and-network` call is pending #3233

Closed frederikhors closed 1 year ago

frederikhors commented 1 year ago

After the big work on https://github.com/urql-graphql/urql/pull/3200 there is an issue in how teardown operations are called on the page reload (when there are cached data).

REPRODUCTION: https://codesandbox.io/p/sandbox/issue-urql-6-duplicated-requests-forked-0ybcue.

Steps:

  1. click on "Todos list"

  2. open the browser Dev Tools's console

  3. reload the page

  4. see in the console before, else followed immediately (and not after the fake delay of the backend) before, op.kind === teardown

What I expect

I expect teardown to be called after the backend fake delay response.

More context

I'm using a custom exchange to track pending requests globally:

const pendingRequestsExchange: Exchange = ({ forward }) => {
  function before(op: Operation) {
    if (op.kind === 'subscription') return;

    if (op.kind === 'teardown') {
      console.log('before, op.kind === teardown');
      // decrease the global pending requests here
    } else {
      console.log('before, else');
      // increase the global pending requests here
    }
  }
  function after(op: OperationResult) {
    console.log('after()');
    // decrease the global pending requests here
  }
  return (ops$) => {
    const forward$ = pipe(ops$, tap(before));
    return pipe(forward(forward$), tap(after));
  };
};

@kitten said that maybe the issue is my custom exchange and that

you will have to adjust your after call to be more precise. If this is just to keep track of global loading states, I'd suggest to be more accurate with cache-only operations in after and/or maybe adding a delay or debounce here.

but the thing is the after() function of the custom exchange is NEVER called on the first load.

I do not understand why the teardown operation is issued. If this is a cache-and-network call it should wait for the server answer, nope?

Thanks for your work, it's not something I take for granted. Really, thanks.

Gif

issue_teardown

kitten commented 1 year ago

This is not a bug, but required for us to issue a new operation: https://github.com/urql-graphql/urql/blob/c356285e050c46022192067151c1ec267424062d/exchanges/graphcache/src/offlineExchange.ts#L160