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)

DEV

Thank you.

 
Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.