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