Hey there! If you've ever worked with React, you know how important routes are—they're what connect different pages or sections of your app. However, dealing with them can be a bit tricky.
So, I came up with a nifty way to handle route paths neatly, all in one file, and easily share them across your entire app.
Let's dive into the code:
export const AppRoutePaths = {
home: '',
auth: 'auth',
project: {
index: 'project',
create: 'create',
manage: {
index: 'manage',
byId: ({ id }: { id: string }) => `${id}`,
},
},
// ... (other routes)
};
function createAppRouterFullPath(routePaths: Record<string, any>, parentPath = '') {
let fullPath: Record<string, string> = {};
for (const key in routePaths) {
const value = routePaths[key as keyof typeof AppRoutePaths];
const propKey = parentPath
? [parentPath, key]
.filter((item) => !item.match(/^(?:false|null|undefined|0|NaN|''|""|`.*?`)$/i))
.join('.')
.replaceAll('/', '.')
: key;
if (typeof value === 'string') {
fullPath[propKey] = parentPath ? `${parentPath}/${value}` : value;
} else if (typeof value === 'function') {
fullPath[propKey] = parentPath
? `${parentPath}/${value({ id: ':id' })}`
: value({ id: ':id' });
} else if (typeof value === 'object') {
const nestedFullPath = createAppRouterFullPath(
value,
parentPath ? `${parentPath}/${key}` : key
);
fullPath = { ...fullPath, ...nestedFullPath };
}
}
return fullPath;
}
export const AppRouterFullPath = createAppRouterFullPath(AppRoutePaths);
Now, let's talk about the purpose of the createAppRouterFullPath function:
If you noticed, the routes inside AppRoutePaths are nested but not connected to their parent. This function helps link them together.
Consider these routes:
export const AppRoutePaths = {
home: '',
auth: 'auth',
project: {
index: 'project',
byId: ({ id }: { id: string }) => `${id}`,
}
If I want to link to auth, I can use:
<Link href={AppRoutePaths.auth} ... />
But what if I'm on the auth route and want to link to byId inside project?
<Link href={AppRoutePaths.project.byId({ id: 'id' })} ... />
Without the createAppRouterFullPath
function, this would redirect to localhost:3000/auth/:id
instead of localhost:3000/project/:id
. The function takes care of joining nested routes with their parent.
Now, how do you use it? Check this out:
const router = useMemo(
() =>
createBrowserRouter([
{
errorElement: <ErrorBoundary />,
element: <Layout />,
children: [
{
path: AppRoutePaths.home, // here
index: true,
element: (
<LazyRoute>
<HomePage />
</LazyRoute>
),
},
// ... (other routes)
],
},
]),
[]
);
I've also thrown in a handy function to add '/' in front of routes when needed, preventing them from becoming relative to the current URL:
export function withSlashPrefix(path: string) {
return `/${path}`;
}
Now linking buttons to pages is a breeze:
<Link href={withSlashPrefix(AppRoutePaths.home)}>
<Button>GoToHome</Button>
</Link>
It's just one of my explorations; I work with React every day, so I frequently encounter issues and discover reasons to build or update things. This is one of those instances.
Voila! Happy routing!
Top comments (0)