DEV Community 👩‍💻👨‍💻

Cover image for The right way to structure your react router
Kachi Cheong
Kachi Cheong

Posted on • Updated on

The right way to structure your react router

React Router Tutorial

People new to react generally don't know how to structure their routes.

Beginners and entry level developers will write something like this:

import "./App.css";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Profile from "./pages/Profile";
import Checkout from "./pages/Checkout";
import Login from "./pages/Login";
import Maps from "./pages/Maps";
import Settings from "./pages/Settings";
import Store from "./pages/Store";

const App = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profile" element={<Profile />} />
        <Route path="/checkout" element={<Checkout />} />
        <Route path="/login" element={<Login />} />
        <Route path="/maps" element={<Maps />} />
        <Route path="/settings" element={<Settings />} />
        <Route path="/store" element={<Store />} />
      </Routes>
    </BrowserRouter>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Although this is acceptable for small projects, when your project scales - this will become incredibly difficult to read.

So we're going refactor the code into this:

import "./App.css";
import { BrowserRouter } from "react-router-dom";
import Router from "./pages/router";

const App = () => {
  return (
    <BrowserRouter>
      <Router />
    </BrowserRouter>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

It's cleaner, scalable and more readble. So let's get started!

Firstly create our React app in typescript by running the following commands in our terminal:

npx create-react-app router-tutorial --template typescript
cd router-tutorial
Enter fullscreen mode Exit fullscreen mode

Create the Pages

We're only going to create two pages, Home and About.

Run the following commands in your terminal:

mkdir src/pages
mkdir src/pages/Home src/pages/About
touch src/pages/Home/index.tsx src/pages/About/index.tsx
Enter fullscreen mode Exit fullscreen mode

What did we just do?

  1. Created pages directory.
  2. Created two directories inside of pages: Home and About.
  3. Created index.tsx files for Home and About.

Add this to your pages/About/index.tsx file:

const About = () => {
  return (
    <div>
      <h1>About</h1>
    </div>
  );
};

export default About;
Enter fullscreen mode Exit fullscreen mode

Add this to your pages/Home/index.tsx file:

const Home = () => {
  return (
    <div>
      <h1>Home</h1>
    </div>
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

This is pretty self explanatory, we've created two files which represent our pages.

Creating the types

Let create our types by running the following commands in our terminal:

mkdir src/types
touch src/types/router.types.ts
Enter fullscreen mode Exit fullscreen mode

Now add this to the newly created types/router.types.ts file:

export interface routerType {
  title: string;
  path: string;
  element: JSX.Element;
}
Enter fullscreen mode Exit fullscreen mode

What is happening?

Declare a type for each route:

  • title: this will be a string
  • path: this will also be a string
  • element: this will be a JSX.Element

Why declare types?

You'll see shortly that declaring the types will make sure each time we add a page object, it will follow a strict rule pattern and won't compile any errors.

Creating the Router

Now we're creating our router.

Run this command in your terminal:

touch src/pages/router.tsx src/pages/pagesData.tsx
Enter fullscreen mode Exit fullscreen mode

Pages Data

Add to pages/pagesData.tsx:

import { routerType } from "../types/router.types";
import About from "./About";
import Home from "./Home";

const pagesData: routerType[] = [
  {
    path: "",
    element: <Home />,
    title: "home"
  },
  {
    path: "about",
    element: <About />,
    title: "about"
  }
];

export default pagesData;
Enter fullscreen mode Exit fullscreen mode

What is happening?

  1. We've imported our pages and types.
  2. Added a title, path and element to each object.

Every time we want to add a new page, all we have to do is add a new page object into this array. The types will be strict so they must each contain a title, path and element.

Router File

Add to pages/router.tsx

import { Route, Routes } from "react-router-dom";
import { routerType } from "../types/router.types";
import pagesData from "./pagesData";

const Router = () => {
  const pageRoutes = pagesData.map(({ path, title, element }: routerType) => {
    return <Route key={title} path={`/${path}`} element={element} />;
  });

  return <Routes>{pageRoutes}</Routes>;
};

export default Router;
Enter fullscreen mode Exit fullscreen mode

What is happening?

We're mapping over the pagesData.tsx file and for each object in our data, we are returning a route.

Update App File

Finally update the App.tsx:

import "./App.css";
import { BrowserRouter } from "react-router-dom";
import Router from "./pages/router";

const App = () => {
  return (
    <BrowserRouter>
      <Router />
    </BrowserRouter>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

And we're all done! Thanks for reading.

Here is the Github repo.

Top comments (0)

In defense of the modern web

I expect I'll annoy everyone with this post: the anti-JavaScript crusaders, justly aghast at how much of the stuff we slather onto modern websites; the people arguing the web is a broken platform for interactive applications anyway and we should start over;

React users; the old guard with their artisanal JS and hand authored HTML; and Tom MacWright, someone I've admired from afar since I first became aware of his work on Mapbox many years ago. But I guess that's the price of having opinions.