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

Stale error state before refetch affecting rendering #1810

Closed
BenStorey opened this issue Dec 7, 2021 · 2 comments
Closed

Stale error state before refetch affecting rendering #1810

BenStorey opened this issue Dec 7, 2021 · 2 comments

Comments

@BenStorey
Copy link

Hi everyone,

I’m having a problem that I’m sure must be common and I’m surprised I can’t find any other questions from people who have the same problem!

I have a component that is getting some data like this:

const { data, error, isLoading } = api.useMyQuery(null);

and everything works fine. But this series of events is causing me trouble:

  • Our component is rendered and eventually the backend call errors, so we have “error” set and we can display it (either in the jsx or a toast with useEffect((), [error]))
  • The user navigates to another link, causing our component to unmount
  • The user then navigates back, so our component will be recreated again
  • My component now sees that “error” is already set, so will show some error details to the user
  • But now rtk-query will immediately refetch the data, setting “error” back to undefined and causing an immediate re-render

This causes strange behaviour (in my case with toasts flickering in/out) but it seems to me like this could be a problem anywhere where we are making rendering decisions based on the now stale data.

I can add a flag to ignore the value in “error” if it’s the first render of the component, but that feels hacky and it feels like I’m not solving this the way its meant to be solved.

Can anyone advise on the proper way to stop this from happening? I’m especially interested when we are showing toasts on the error, as the only other option I can see is putting them into a middleware (like the example in the docs using isRejectedWithValue()) but it feels wrong to bury all my error notifications in a middleware that’s so far away from where the request was created.

Thanks everyone,

@markerikson
Copy link
Collaborator

Heh, David Khourshid has commented about this kind of scenario:

#349 (comment)

Quoting:

because 'showAlert' is an effect that is only executed on the transition between loading and error, it will only be executed once, which is what you would expect. No hacks!

To emulate this, you need to somehow represent this "transition", so the useEffect code would need to be refactored to look something like this:

// pseudocode!!
useEffect(() => {
  if(error && previousStateWas(loading)) {
    showSnackbarForFiveSeconds(error);
  }
}, [error]);

FWIW, a middleware is a valid option here, because triggering the toast based on the action is at least more "one-time" and conceptually similar to the "transition" that David was talking about.

We actually have a new in-development "action listener" middleware that might be useful for that if you'd like to try it out:

#1648

@BenStorey
Copy link
Author

Thanks Mark. I'll give your middleware a try!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants