DEV Community

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

Posted on

3 1

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!

SurveyJS custom survey software

Simplify data collection in your JS app with a fully integrated form management platform. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more. Integrates with any backend system, giving you full control over your data and no user limits.

Learn more

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay