DEV Community

Cover image for React - dynamic routing
Ivan Kranjec
Ivan Kranjec

Posted on

React - dynamic routing

What are we going to learn?

  1. How to implement dynamic routing.
  2. How to mirror route changes to some kind of navigation.
  3. How to implement "Not Found" page.

End result

Notes

  1. This example will use React Suite pack of UI components.

  2. Code can be found here.

1. Implementing dynamic routing and mirroring changes to sidebar navigation

Here we need to create a list of routes.

export const Router = [
    {
        title: "Home",
        icon: <FolderFillIcon />,
        route: "",
        component: <Home />
    },
    {
        title: "About us",
        icon: <GridIcon />,
        children: [
            {
                title: "Contact us",
                icon: <ReviewIcon />,
                route: "/contact-us",
                component: <Contact />
            },
            {
                title: "Become a partner",
                icon: <GlobalIcon />,
                route: "/partner-program",
                component: <PartnerProgram />
            }
        ]
    }
]
Enter fullscreen mode Exit fullscreen mode
  • Title - name of the route in navigation.
  • Icon - suitable icon component from React Suite
  • Route - path to page
  • Component - this will represent a page we wish to render at a current route

It is time to create a navigation component.
Navigation will be implemented via Sidenav component from rsuite.

In case there are children on current route, we should render some kind of navigational menu (dropdown), and use children to display them as navigation items (links).

If children are not present in current route, then just render a simple navigation item (link).

This part of navigational logic is implemented via NavigationItem component.

export const NavigationItem = ({ icon, route, title, childRoutes }) => {
  const navigate = useNavigate();

  return (
    <>
      {childRoutes && (
        <Nav.Menu title={title} icon={icon}>
          {childRoutes &&
            childRoutes.map((x) => {
              return (
                <Nav.Item
                  onClick={() => navigate(x.route)}
                  children={x.title}
                  icon={x.icon}
                />
              );
            })}
        </Nav.Menu>
      )}
      {!childRoutes && (
        <Nav.Item
          onClick={() => navigate(route)}
          children={title}
          icon={icon}
        />
      )}
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

Navigation component implementation should look like this.
Routes are rendered via NavigationItem component inside Nav component.

export const Navigation = ({
  appearance,
  expanded,
  onOpenChange,
  onExpand,
  ...navProps
}) => {
  return (
    <div className={"navigation"}>
      <Sidenav
        appearance={appearance}
        expanded={expanded}
        onOpenChange={onOpenChange}
      >
        <Sidenav.Body>
          <Nav {...navProps}>
            {Router.map((x) => {
              return (
                <NavigationItem title={x.title} route={x.route} icon={x.icon} childRoutes={x.children} />
              );
            })}
          </Nav>
        </Sidenav.Body>
        <Sidenav.Toggle onToggle={onExpand} />
      </Sidenav>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode
  • appearance - menu style defined by React Suite
  • expanded - whether sidebar is expanded
  • onOpenChange - navigation opening callback function
  • onExpand - navigation expand callback function

Final step in implementing dynamic routing is to define layout in App.js and map all routes there in some kind of "container", so content of current route can be properly rendered.

export const App = () => {
  const [expanded, setExpand] = React.useState(true);
  const routes = Router.filter((r) => r.title).concat(
    Router.filter((r) => r.children && r.children.length)
      .map((r) => r.children)
      .flat()
  );

  return (
    <>
      <div>
        <Container>
          <Sidebar
            className={'sidebar'}
            width={expanded ? 260 : 56}
            collapsible
          >
            <Navigation
              expanded={expanded}
              onExpand={setExpand}
            />
          </Sidebar>
          <Content>
            <Routes>
              {routes.map((x) => {
                return (
                  <>
                    <Route path={x.route} element={x.component} />
                  </>
                );
              })}
              <Route path={"*"} element={<NotFound />} />
            </Routes>
          </Content>
        </Container>
      </div>
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

2. Creating "Not Found" page.

In case user types random route in browser search bar, it would be nice to redirect him to classic "Not Found" page.

Not found page

What we need to do is create our NotFound React component (page).

export const NotFound = () => {
    return (
        <Page header={'Content not found!'}>
            <GearIcon spin className={'gear-icon'} />
        </Page>
    )
}
Enter fullscreen mode Exit fullscreen mode

Last thing we need to do to make sure this works is to add NotFound page to our router in App.js manually. It should be added as last route.

<Route path={'*'} element={<NotFound />} /> 
Enter fullscreen mode Exit fullscreen mode

Thank you for reading!

Top comments (0)