Logo

dev-resources.site

for different kinds of informations.

createBrowserRouter A step up from Switch

Published at
5/18/2024
Categories
webdev
routing
reactrouter
createbrowserrouter
Author
mvaja13
Author
7 person written this
mvaja13
open
createBrowserRouter A step up from Switch

What is Routing? Why Do We Need It? 🧭

Routing is how you navigate in a web application. It allows you to map URL paths to specific components, enabling users to access various parts of your app without needing to reload the page.
Routing is important because it ensures a seamless user experience, making your app feel similar to a desktop application. It helps in organizing and managing different views, maintaining a clean and efficient codebase, and enabling features like deep linking and dynamic content loading.

The Good Ol' Days of Switch

Back in the day, we used the Switch component to handle routing in React. It was straightforward and did the job well by rendering only the first child <Route> that matched the location.

Here’s a simple example using Switch:

import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Contact from "./components/Contact";

function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />
      </Switch>
    </Router>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Pretty neat, right? But as our apps grew more complex, Switch started to show its limitations.

Problems and Limitations of Switch 😬

1. Lack of Nested Routes

One major limitation of Switch was its lack of built-in support for nested routes. In complex applications, it's common to have layouts where some components remain constant (like headers or sidebars) while others change based on the route. With Switch, achieving this required cumbersome workarounds and additional code, making the routing setup harder to manage and maintain.

2. Limited Error Handling

Error handling was another area where Switch fell short. If a user navigated to a non-existent route, handling this gracefully required extra effort. Typically, developers had to add a catch-all route at the end of the Switch component, which wasn't always intuitive or straightforward.

<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
  <Route path="/contact" component={Contact} />
  <Route component={NotFound} /> {/* Catch-all route for 404 errors */}
</Switch>
Enter fullscreen mode Exit fullscreen mode

3. Verbose and Repetitive Code

For larger applications, the Switch setup could become quite verbose and repetitive. Each route had to be defined explicitly within the Switch block, leading to cluttered and less maintainable code. This verbosity made it harder to manage and refactor routes, especially as the application grew.

4. Limited Data Fetching Capabilities

Handling data fetching and route-based data loading wasn't straightforward with Switch. Developers often had to rely on external libraries or custom hooks to fetch data before rendering a component, leading to fragmented code and a less cohesive approach to routing and data management.

5. Poor Integration with Modern React Features

As React evolved with new features like hooks and concurrent rendering, Switch didn't keep pace. Integrating these modern features into the routing logic required additional effort and custom solutions, making it harder to leverage the full power of React's latest advancements.

Say Hello to createBrowserRouter 👋

With the release of React Router version 6, we got createBrowserRouter. It’s packed with powerful features that make routing in React apps easier and more efficient.

Setting Up createBrowserRouter

npm install react-router-dom
# or
yarn add react-router-dom
Enter fullscreen mode Exit fullscreen mode

Now, let’s get into setting up createBrowserRouter.

Basic Setup

  1. Import Necessary Functions:

Start by importing the required functions from react-router-dom:

import { createBrowserRouter, RouterProvider } from "react-router-dom";
Enter fullscreen mode Exit fullscreen mode
  1. Define Routes:

Next, define the routes for your application. Here’s a simple example:

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
  },
  {
    path: "about",
    element: <About />,
  },
  {
    path: "contact",
    element: <Contact />,
  },
]);
Enter fullscreen mode Exit fullscreen mode

In this setup, we have three routes: /, /about, and /contact, each rendering a different component.

Rendering the Router

To render the router, use the RouterProvider component and pass in the router object:

function App() {
  return <RouterProvider router={router} />;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Cool New Features in createBrowserRouter 🤩

Nested Routes

Nested routes are super handy for managing complex applications. They let you define routes within other routes, which is great for layouts where some components are always visible (like a navigation bar) while others change based on the route.

Here’s how you can define nested routes:

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
    children: [
      {
        path: "about",
        element: <About />,
      },
      {
        path: "contact",
        element: <Contact />,
      },
    ],
  },
]);
Enter fullscreen mode Exit fullscreen mode

In this example, About and Contact are nested within the Home route.

Route Parameters

Need to capture values from the URL? Route parameters have got you covered. This is especially useful for dynamic routing, like displaying user profiles or articles based on an ID.

import UserProfile from "./components/UserProfile";

const router = createBrowserRouter([
  {
    path: "/user/:userId",
    element: <UserProfile />,
  },
]);
Enter fullscreen mode Exit fullscreen mode

In this setup, the UserProfile component will receive a userId parameter from the URL, which can be accessed within the component using hooks like useParams.

Error Handling

You can define error handling routes to display custom error pages for specific conditions:

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
    errorElement: <NotFound />,
    children: [
      {
        path: "about",
        element: <About />,
      },
      {
        path: "contact",
        element: <Contact />,
      },
    ],
  },
]);
Enter fullscreen mode Exit fullscreen mode

In this example, if a route is not found, the NotFound component will be rendered.

Data Fetching

React Router 6 introduces the ability to define loaders and actions for routes, which can handle data fetching and mutations. This ensures data is loaded before a component is rendered:

import { createBrowserRouter } from "react-router-dom";
import Home from "./components/Home";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
    loader: async () => {
      const data = await fetchData();
      return { data };
    },
  },
]);

async function fetchData() {
  // Fetch your data here
  return fetch("/api/data").then((res) => res.json());
}
Enter fullscreen mode Exit fullscreen mode

In this example, fetchData is called before rendering the Home component, ensuring the component has the necessary data.

Best Practices

Organize Routes

Organize your routes in a separate file to keep your code clean and maintainable. For example, create a routes.js file:

// routes.js
import Home from "./components/Home";
import About from "./components/About";
import Contact from "./components/Contact";

const routes = [
  {
    path: "/",
    element: <Home />,
    children: [
      {
        path: "about",
        element: <About />,
      },
      {
        path: "contact",
        element: <Contact />,
      },
    ],
  },
];

export default routes;
Enter fullscreen mode Exit fullscreen mode

Then, import and use this in your main file:

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import routes from "./routes";

const router = createBrowserRouter(routes);

function App() {
  return <RouterProvider router={router} />;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Use Lazy Loading

For better performance, use lazy loading to load components only when needed. React’s lazy and Suspense can help with this:

import React, { lazy, Suspense } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

const Home = lazy(() => import("./components/Home"));
const About = lazy(() => import("./components/About"));
const Contact = lazy(() => import("./components/Contact"));

const router = createBrowserRouter([
  {
    path: "/",
    element: (
      <Suspense fallback={<div>Loading...</div>}>
        <Home />
      </Suspense>
    ),
    children: [
      {
        path: "about",
        element: (
          <Suspense fallback={<div>Loading...</div>}>
            <About />
          </Suspense>
        ),
      },
      {
        path: "contact",
        element: (
          <Suspense fallback={<div>Loading...</div>}>
            <Contact />
          </Suspense>
        ),
      },
    ],
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Conclusion

createBrowserRouter is a big step up from the traditional Switch component, offering enhanced flexibility and functionality. With features like nested routes, route parameters, error handling, and data fetching, you can create dynamic and efficient routes for your projects.

For more info refer the documentation

routing Article's
30 articles in total
Favicon
Mastering Nested Navigation in Flutter with `go_router` and a Bottom Nav Bar
Favicon
Understanding ShellRoute in go_router: Managing Shared Layouts Effectively
Favicon
How the Web Evolved: The Rise of Single Page Applications
Favicon
Introducing Humiris MoAI Basic : A New Way to Build Hybrid AI Models
Favicon
TanStack Router: The Future of React Routing in 2025
Favicon
Next.js: Dynamic Routing with API Integration.
Favicon
Learning Next.js 13 App Router: A Comprehensive Guide 🚀
Favicon
Organizing Your Routes Modularly and Automatically in Lithe
Favicon
Organizando Suas Rotas de Forma Modular e Automática no Lithe
Favicon
🗺️ Peta Jalan Laravel: Menjelajah Routing, Middleware, dan Controller (Indonesian Version)
Favicon
Working On a React / Python Flask Back End Web App.
Favicon
Vue.js for Beginners 2024 #VueJs Part 5 : A Complete Guide to Routing with Vue Router
Favicon
Mastering Routing Protocols with Cisco Packet Tracer: A Learning Experience
Favicon
Restful Routing - A Flask API Example
Favicon
Routing in React vs. Next.js: Extra Work or Easy Wins?
Favicon
Browser refresh on click of Home button using href
Favicon
Decorate the Symfony router to add a trailing slash to all URLs
Favicon
Routing in Umbraco Part 2: Content Finders
Favicon
Routing in Umbraco Part 1: URL segments
Favicon
Simplifying Network Administration: BGP Route Servers' Function in the Internet Ecosystem
Favicon
createBrowserRouter A step up from Switch
Favicon
Mastering Angular 17 Routing
Favicon
Snag the Current URL in SvelteKit (2024 Edition)
Favicon
Ensuring Type Safety in Next.js Routing
Favicon
Laravel 11: Health Check Routing Example
Favicon
Switch'in L2 mi L3 mü Olduğunun Öğrenilmesi
Favicon
Routing with React Router
Favicon
Routing implementation using PHP attributes
Favicon
What is Vinxi, and how does it compare to Vike?
Favicon
Fallback Routing with Axum

Featured ones: