Adding react router to a react app

Kum SomiKum Somi
6 min read

Introduction

We mostly use react-router for changing the routes of our project.

Let's say I'm building an e-commerce app that would take me to different pages like the home page, product page, cart page, wishlist page, and orders page. To redirect my app from one page to another we use a React router.

Installation:-

npm i react-router-dom

Getting Started

  • Wrap the app with a browser router. A <BrowserRouter> stores the current location in the browser's address bar using clean URLs and navigates using the browser's built-in history stack.

      <BrowserRouter>
          <App />
      </BrowserRouter>
    
  • Use <Routes> for matching the best match of the URL. Whenever the location changes, <Routes> looks through all its child routes to find the best match and renders that branch of the UI.

      <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/login" element={<Login />} />
      </Routes>
    
  • <Route/> tells the app which element should render on the screen at a particular route in the URL.

Representing a nested UI using <Route/>

  • Let's assume, We have a designated layout for the header, main and footer which is displayed as it is on every page, just the content of the main changes.

      <body>
        <navbar />
        <main />
        <footer/>
      </body>
    
  • In that case, are we going to write the navbar and footer on every page?

  • No, we can instead use nested <Route/>. This means, we can create a <Layout/> component (let's say consisting of navbar, footer) and then render other components as its child, making it a nested UI tree, which corresponds to nested child routes.

      <Routes>
         <Route path="/" element={<Layout />}>        
            <Route index element={<Home />} />
            <Route path="/login" element={<Login />} />
            <Route path="/signup" element={<Signup />} />
         </Route>
      </Routes>
    
  • For this to work, the parent route element should contain <Outlet/>. So that, the nested UI will be displayed on the page whenever any child route is rendered.

  • If the parent route is matched exactly, it will render a child index route or nothing if there is no index route. This means in the above case whenever "/" is the path of the URL, <Home/> component along with the layout will be shown on the screen.

      export const Layout = () => {
        return (
          <>
            <Navbar />
            <Outlet />
          </>
        );
      };
    

    Understanding path of <Route/>

    The path matches with the exact URL.

    Dynamic path - A slash followed by a colon is how we represent dynamic paths /: and anything after the colon will be provided in terms of params.

      <Route 
              // above path will support
              // /products/:xy12z4598 as a dynamic route 
              // where xy12z4598 is the productId params.
          path="/products/:productId" 
          element={<Layout />}
      />
    

    Optional Segment of path -

      <Route
              // this path will match URLs like
              // - /categories
              // - /en/categories
              // - /fr/categories
              path="/:lang?/categories"
              element={<Categories />}
       />
    

    Catch All segment - * can catch all the possible URL's. This is mostly used to show not found page when user enters an un-specified URL

      <Route 
          path="/*" element={<NotFound/>}
      />
    

    index path - Index routes render into their parent's Outlet at their parent's URL (like a default child route).

      <Route path="/" element={<Layout />}>
            <Route index element={<Home />} /> 
             // Home component will be rendered for the URL /
             // <Home/> is considered as default child because of index.
      </Route>
    

Path Matching

The ranking of routes depends on the behaviour of the segments of the path

1- Static Segment.

2- Dynamic Segment

3- Star patterns

Least dynamic URLs would be given more priority or tend to be more specific.

Static > Dynamic> Star pattern

// url= "products/new"

// -> /products/:productId

// -> /products/new" --> this is the least dynamic(most static) 
//                      --> prioritised

// -> *

<Routes>
    <Route path="/products" element={<Products />} />
    <Route path="/products/:productId" element={<SingleProduct />} />
    <Route path="/products/new"/>
    <Route path="*" element={<NotFound/>}/>
</Routes>

Using the routes through <Link/>

  • We use <Link/> tag to navigate instead of anchor tag <a></a>.

      <nav>
          <Link to="/login">Login</Link>
          <Link to="/signup">Signup</Link>
      </nav>
    
  • Link to value should match with one of the <Route/> paths specified in the app.

Q: On any site, how do you get to know which page you are currently browsing?

A: Through an active link of the navigation.

Q: How do we add active links on the page?

Replacing <Link/> with <NavLink/>

<NavLink/> - NavLink is a special type of <Link/> that knows if a link is active (clicked) or pending(not clicked). This is useful while building tabs, breadcrumbs or navbar.

  • NavLink using className
<NavLink to="/posts" 
         className={
             ({isActive, isPending})=>
                 ( isPending? "unselected": isActive ? "selected-link" : "" )
          }
/>
    Posts
</NavLink>
  • NavLink using style prop
<NavLink
        to="/posts"
        style={({ isActive, isPending }) => {
          return {
            fontWeight: isActive ? "bold" : "",
            color: isPending ? "red" : "black",
          };
        }}
      >

        Posts
</NavLink>

Scenario: In a blogging site, Clicking on an article on the home page should take us to a Single-page article.

Step 1: Identify the unique ID for all the posts.

const post = [
        {
            id: '101article-on-hashing',
            title:'hashing technique'
        },
        {
            id:'102article-on-CDN',
            title:'CDN piple'
        } 
]

Step 2: Make a link dynamic

id="102article-on-CDN"  

<Link to={`/posts/${id}`}>

    CDN pipleline article

</Link>

Step 3: Define the dynamic link in the <Routes>

 <Route 
        path="/posts/:postId" 
        element={<SingleArticlePage/>} 
 />

Step 4: Read the details from the dynamic routes using useParams() hook.

//read the details at SingleArticlePage

const SingleArticlePage=()=>{
    const { postId } = useParams(); 
 // gives us the exact id of which post is clicked from the home page.

    return (
        <div>
            <h3>PostID : {postID}</h3>
            <!-- to show the other details of the  as well -->
            {AllPost.filter(post.id === postIdUrl).map(post => (
                  <div>
                      <h1>{post.title}</h1>
                      <h3>{post.description}</h3>
                  </div>)
             )}    
        </div>
    );
}

Summary

  • Routers are used to dynamically move from one page to another, they keep track of all the pages and put them in the browser history stack.

  • Specify all the routes and use the routes through <Link/>.

  • Use active link styles for the nav link.

  • Adding dynamic routes through /:id and accessing the id from the URL using useParams() to create unique links.

References:-

  1. React router official documentation:- https://reactrouter.com/en/main

Wrapping up

We learned about the react routers and how we can use them in our project to move from one link to another without a page refresh.

  • Want to continue this discussion? Or have any feedback for me? Write down in the comments below.

  • Let's connect on Twitter, or write to me at kumsomi.5@gmail.com.

Thanks for reading.

Until next time, take care, keep Reading and keep spreading happiness.

0
Subscribe to my newsletter

Read articles from Kum Somi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kum Somi
Kum Somi

Hey, I am a self-made developer who is trying to learn new things every day.