nahuel.luca()

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>
  );
}