Next.js Discord

Discord Forum

Loading state for multiple events

Unanswered
Polar bear posted this in #help-forum
Open in Discord
Polar bearOP
Next.js 14, app router, client component. My logout click handler has this async code:

const { error } = await supabase.auth.signOut();

if (error === null) {
  showNotification({
    title: t('bye'),
    message: t('logoutMessage'),
    icon: <IconCheck stroke={1.5} />,
    color: 'green',
  });
  setProfile(null);
  router.push('/login');
}


It executes a logout request, and if successful, shows a notification, sets the global user profile state to null and navigates to '/login'. I want to display a constant loading state while this code is executing. It must start immediately after the click, and end after login page has loaded.

loading.tsx works only while the /login route is rendering, so it's not responsive enough.

By utilizing the useTransition hook I can get an immediate loading state that ends after router.push('/login'), but it won't wait for the rendering. Also I feel a bit dirty using it, because (afaik) it should take a synchronous function that only has state updates. So I'm not sure if this is the right tool either.

Is there any built-in solution for this, like subscribing to router events?

1 Reply

Polar bearOP
I figured that I could use useTransition and nested startTransition calls. I get the boolean flag at the top level:
const [isPending, startTransition] = useTransition();


Previously I tried this, which didn't wait for the rendering to finish:
startTransition(async () => {
  const { error } = await supabase.auth.signOut();
  if (error === null) {
    showNotification({
      title: t('bye'),
      message: t('logoutMessage'),
      icon: <IconCheck stroke={1.5} />,
      color: 'green',
    });
    setProfile(null);
    router.push('/login');
  }
});


This works almost the way I want, except there is a flash between the transitions:
startTransition(async () => {
  const { error } = await supabase.auth.signOut();
  if (error === null) {
    showNotification({
      title: t('bye'),
      message: t('logoutMessage'),
      icon: <IconCheck stroke={1.5} />,
      color: 'green',
    });
    setProfile(null);
    startTransition(() => {
      router.push('/login');
    });
  }
});