Skip to Content
BlogRender modal on a route with the parent in background with Tanstack Router

Render modal on a route with the parent route rendered in background in Tanstack Router

beautiful-bird

📸

Pexels

Modals are one of the most versatile UI patterns in modern web development. They allow us to present focused content without losing context of the underlying page. And it also helps us to improve the user experience and SEO.

Today, I’ll walk you through creating modal routes using Tanstack Router  - a powerful, type-safe routing solution for React applications. We’ll build a gallery where clicking on images opens them in a modal while keeping the gallery visible in the background.

Why Modal Routes Matter 🎯

Modal routes are perfect for scenarios where you want to:

  • Show detailed views: Display item details, user profiles, or product information without losing the list context
  • Handle forms: Present forms for editing, creating, or configuring while keeping the parent page accessible
  • Improve UX: Maintain user context and reduce navigation friction
  • Deep linking: Allow users to share direct links to modal content
  • SEO: Better for SEO as the modal is a separate route

You can do the same thing with react-router-dom and Next.js. you can checkout those articles later.

Prerequisites 📋

Before we dive in, make sure you have:

  • A basic understanding of React  and TypeScript
  • Familiarity with Tanstack Router  concepts (if not, check their excellent documentation)
  • A React project set up with TypeScript support

We’ll be building a product photo gallery application where users can browse images and click to view them in a modal overlay.

Install Tanstack Router

First, let’s set up Tanstack Router in our project. We’ll use the createRouter function to define our routes.

npm install @tanstack/react-router # or pnpm add @tanstack/react-router # or yarn add @tanstack/react-router

So since in tanstack router we can implement the routing in two ways, file based and code based.

I will not write the code here i will provide the github repo link. so you can explore and learn from it.

File Based Routing

In file based routing we can create a folder and inside that folder we can create a file for each route or we can use the . for child routes like in the example below.

and the whole code is available in the github repo .

    • __root.tsx
    • about.tsx
    • index.tsx
    • photos_$id.tsx
    • photos.{$id}_modal.tsx
    • photos.tsx

Code Based Routing

In other hand we can use the code based routing to create the routes. code based routing works similar to react-router-dom.

The whole code is available in the github repo .

      • __root.tsx
      • about.tsx
      • index.tsx
      • photos-id.tsx
      • photos-modal.tsx
      • photos.tsx
    • main.tsx

This is how the main file should look like.

main.tsx
import { StrictMode } from 'react' import ReactDOM from 'react-dom/client' import { createRouteMask, createRouter, RouterProvider, } from '@tanstack/react-router' // ROUTES import { rootRoute } from './routes/__root' import { aboutRoute } from './routes/about' import { indexRoute } from './routes/index' // PHOTOS ROUTES import { photosRoute } from './routes/photos' import { photoChildRoute } from './routes/photos-id' import { photoModalRoute } from './routes/photos-modal' const routeTree = rootRoute.addChildren([ indexRoute, aboutRoute, photoChildRoute, photosRoute.addChildren([photoModalRoute]), ]) // Create a route mask for the photo modal to photo route const photoModalToPhotoMask = createRouteMask({ routeTree, from: '/photos/$id/modal', to: '/photos/$id', params: true, }) // Set up a Router instance const router = createRouter({ routeTree, routeMasks: [photoModalToPhotoMask], scrollRestoration: true, }) // Register the router instance for type safety declare module '@tanstack/react-router' { interface Register { router: typeof router } } // Render the app const rootElement = document.getElementById('root')! if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement) root.render( <StrictMode> <RouterProvider router={router} /> </StrictMode> ) }

This is how the root file looks like.

__root.tsx
import { createRootRoute, Outlet } from '@tanstack/react-router' import Navbar from '../_components/navbar' type PhotoModal = { id: 'photo' photoId: string } type ModalObject = PhotoModal export const rootRoute = createRootRoute({ validateSearch: (search) => search as { modal?: ModalObject }, component: RootComponent, }) function RootComponent() { return ( <> <Navbar /> <Outlet /> </> ) }

What We’ve Built 🎉

Congratulations! You’ve successfully implemented a modal route system using Tanstack Router. Here’s what we accomplished:

  • Type-safe routing: All routes and parameters are fully typed
  • Nested routing: The modal renders as a child route while preserving the parent
  • Deep linking: Modal URLs are shareable and bookmarkable
  • Smooth UX: Users can navigate back to the gallery without losing context

Key Benefits of Tanstack Router

  • File-based routing: Routes are defined in separate files for better organization
  • Type safety: Full TypeScript support with automatic type inference
  • Modern patterns: Built for React 18+ with concurrent features
  • Developer experience: Excellent tooling and debugging capabilities

Conclusion

I hope you find this article helpful.

You can checkout the github repo  for the code.

Happy coding! 🚀

Comments

Leave a comment or reaction below!

Last updated on