reactjstypescripttanstacktanstack-router

Tanstack Router does not render redirected route after query error


I am using @tanstack/react-router and @tanstack/react-query in my React application. I have set up a QueryClient to handle errors and redirect to a login page if a 401 Unauthorized error occurs. However, after the redirection, the URL changes to /login but the content does not update to show the login page until I manually interact with the page (e.g., clicking a link).

import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider, createRouter, redirect } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";
import {
  QueryCache,
  QueryClient,
  QueryClientProvider,
} from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import "./index.css";
import "./i18n";

const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error) => {
      router.navigate({ to: "/login" });
    },
  }),
});

export const router = createRouter({ routeTree, context: { queryClient } });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

const rootElement = document.getElementById("root")!;
if (!rootElement.innerHTML) {
  const root = ReactDOM.createRoot(rootElement);
  root.render(
    <StrictMode>
      <QueryClientProvider client={queryClient}>
        <RouterProvider router={router} />
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </StrictMode>
  );
}

Solution

  • You can check the unauthorize attempt by using beforeLoad in parent component. Like:

    // src/routes/_authenticated.tsx
    export const Route = createFileRoute('/_authenticated')({
      beforeLoad: async ({ location }) => {
        if (!isAuthenticated()) {
          throw redirect({
            to: '/login',
            search: {
              // Use the current location to power a redirect after login
              // (Do not use `router.state.resolvedLocation` as it can
              // potentially lag behind the actual current location)
              redirect: location.href,
            },
          })
        }
      },
    })
    

    Code Example