DEV Community

Cover image for Reverse patterns to URL. React router Config.
Ihor Maslov
Ihor Maslov

Posted on

Reverse patterns to URL. React router Config.

In this post, I would like to introduce my approach to "Named URLs" for React Router.

Motivation

I used to use Django's URLs reverse function. This function is beneficial when you need to get an actual URL using a named URL pattern or callable view object.
I want to use a similar approach with React Router.

Problems

The problems I am trying to solve are:

  1. Avoid hard-coded URLs. In the most examples I found, URLs hard-coded in Link. I feel like this can lead us to broken links during refactoring, etc.
  2. Missing URL params. It is difficult to identify Hard-coded links with missed params until you click on them.

Solution

The project directories are structured this way.

The Reverse implementation.

// src/shared/utils/namedUrls.js

import { compile } from 'path-to-regexp';

export class RoutePath {
  reverse(params) {
    const reversed = compile(this.pattern);
    return reversed(params);
  }

  constructor(pattern, component) {
    if (!pattern || !component) throw new Error('`pattern` and `component` are required');
    this.pattern = pattern;
    this.component = component;
  }
}
Enter fullscreen mode Exit fullscreen mode

This class helps us build a route that knows how to build a link using given parameters and patterns.

The usage.

In the app directory.

// src/apps/account/routes.js

import SignInPage from 'apps/account/pages/SignIn';
import UserPage from 'apps/account/pages/User';
import { RoutePath } from 'shared/utils/namedUrls';

const basePath = '/account/';
export default {
  signIn: new RoutePath(`${basePath}sign-in/`, SignInPage),
  user: new RoutePath(`${basePath}user/:id/`, UserPage),
};
Enter fullscreen mode Exit fullscreen mode

In the main routes.js.

// src/routes.js

import { prepareRoutes } from 'shared/utils/namedUrls';

import accountRoutes from './apps/account/routes';

export const routes = {
  accountRoutes,
};

export const preparedRoutes = prepareRoutes(routes);
Enter fullscreen mode Exit fullscreen mode

In components

import React from 'react';
import { Link } from 'react-router-dom';
import { routes } from 'routes';

const SomeComponent = () => (
  <>
    <Link to={routes.accountRoutes.signIn.reverse()}>Sign In</Link>
    <Link to={routes.accountRoutes.user.reverse({ id: 1 })}>User</Link>
  </>
);

export default SomeComponent;
Enter fullscreen mode Exit fullscreen mode

Rendered links are:

<a href="/account/sign-in/">Sign In</a>
<a href="/account/user/1/">User</a>
Enter fullscreen mode Exit fullscreen mode

Error handling

I didn't implement any additional error handling as I am satisfied with the path-to-regexp app's error handling.
If you miss some URL pattern parameters, you will find errors like the below in the browser console.

index.ts:337 Uncaught TypeError: Expected "id" to be a string
    at index.ts:337
    at RoutePath.reverse (namedUrls.js:12)
    at App (App.js:62)
Enter fullscreen mode Exit fullscreen mode

I suppose this will be enough to warn developers that they missed the URL pattern's parameters. And I feel like these errors should be helpful during e2e testing.

Feedback is welcome!

Top comments (0)