loader.tsx
Back to the Codex

FolioJUL MMXXIV

How to create conditional routes in Remix

Conditional Routes in Remix

This post evaluates how to recreate conditional paths as NextJS has. In NextJS we define our routes with for example app/dashboard in this route file we need a layout.tsx and we create 2 slots that are defined with @folder, in this case, @user/page.tsx and @admin/page.tsx.

export default function Layout({
  user,
  admin,
}: {
  user: React.ReactNode;
  admin: React.ReactNode;
}) {
  const role = "admin";
  return <>{role === "admin" ? admin : user}</>;
}

With this, Next conditionally renders the path without changing the /dashboard URL.

How can this be replicated with Remix?

Well, first of all you have to create a dashboard/index.tsx file inside the routes folder. This will define the layout of all the children of /dashboard. Then we will use the <Outlet /> component which will render the matching child path of a parent path and pass the role context to it.

import { Outlet } from "@remix-run/react";

export default function index() {
  const role = "admin";
  return (
    <section className="max-w-[1200px] mx-auto mt-20">
      <h1 className="text-2xl font-bold">Welcome to Dasboard</h1>
      <Outlet context={role} />
    </section>
  );
}

Now we will create our dashboard._index/route.tsx route that will access the <Outlet /> context to receive the role.

import { useOutletContext } from "@remix-run/react";
import Admin from "./admin";
import User from "./user";

export default function Route() {
  const role: string = useOutletContext();
  return <div>{role === "admin" ? <Admin /> : <User />}</div>;
}

There are other ways to achieve something similar with remix without using the context of our <Outlet />, but I find it a good resource because it gives us more flexibility since it is accessible from all the /dashboard child routes, for example dashboard/me.

// routes/dashboard.me/route.tsx
import { useOutletContext } from "@remix-run/react";

export default function Route() {
  const role: string = useOutletContext();
  return (
    <div>
      {role === "admin" ? (
        <h1>Hello you are a Admin</h1>
      ) : (
        <h1>Hello you are a User</h1>
      )}
    </div>
  );
}