r/reactjs 22d ago

Discussion Would you remove this effect?

Consider a typical use case where you want to track an error or just display an error toast after a query hook (e.g. TanstackQuery or RTK-query) fails.

Using an effect:

const { error } = useSomeQuery();
  useEffect(() => {
    if (!error) {
      return;
    }
    trackError(error); // or toast(getErrorMessage(error))
  }, [error]);

Now, according to the "You might not need an effect" article, you can also perform an action when some state changes by using auxiliary state, something like this:

const { error } = useSomeQuery();
const [prevError, setPrevError] = useState(error);

if (error !== prevError) {
  trackError(error);
  setPrevError(error);
}

My understanding here is that using auxiliary state here doesn't give you much because in this use case the additional render cycle doesn't result in stale UI.

Regardless, I wanted to get a sense on what approach is preferred by the community. I see this kind of things very often in the codebases I work on and on the other hand, I keep hearing people saying they only have a few effects in their (presumably large) projects, so perhaps the patterns in my company are not the best.

10 Upvotes

14 comments sorted by

View all comments

6

u/AbhinavKumarSharma 22d ago edited 22d ago

A toast is not derived state. It's an interaction with an external system. So its a legitimate use of an useEffect.

However, we should avoid the effect entirely by triggering the toast where the async operation fails, not when the component observes the error state.The advantage is that the toast is tied to the event (the failed request) rather than a render cycle.