DEV Community

Cover image for Building in Public: React Image Layout with Flexbox and Grid - ACT 4: Mastering React Router and Responsive Navigation
Voke
Voke

Posted on

Building in Public: React Image Layout with Flexbox and Grid - ACT 4: Mastering React Router and Responsive Navigation

EPISODE ONE: react-image-rendering
ACT 4:
ACT 4:PART ONE:

INTRO/RECAP:
{In the last ACT, we covered the basics of React components. We created two components: MainNavigation and Layout, adding SCSS styling to MainNavigation for a polished look. We also explored the children prop in React, understanding how it enables components to wrap other content seamlessly. Finally, we integrated the App component with our Layout component to ensure everything renders correctly in the web browser.}.

Link to ACT3 Here

The following events take place in ACT 4:

ACT 4:PART TWO:
Handling the Deprecation Warning:

Alright, before we go further, there is a minor issue I have noticed when we run our app. We get a kinda warning in the terminal. A Deprecation Warning that reads: Deprecation Warning: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
More info: https://sass-lang.com/d/legacy-js-api

I was a little bit confused at first, it had me thinking that the usual installation for my Scss was wrong or something. So I did a quick stackoverflow check and saw something helpful there. It appeared someone had also faced this kinda issue. Mind you, you can still work with the warning, it's not going to prevent you from working. But I felt I needed to get rid of it. So a response I found on stackoverflow says and I quote "The default API when using Vite is currently set to legacy, but you can change it in your vite.config.[js/ts]."

This was the code that was suggested we add:

export default defineConfig({
  css:{
    preprocessorOptions:{
      scss:{
        api:"modern-compiler"
      }
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

So I will go inside my vite.config.ts file and make some changes. After making the changes, this is how my code would look in the file:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server:{
    port:3000
  },
  css:{
    preprocessorOptions:{
      scss:{
        api:"modern-compiler"
      }
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

Then ctrl + S. This will restart the dev server.
And hopefully remove the Warning.

ACT 4:PART THREE:
Enhancing the Styling in MainNavigation:

With that out of the way, lets revisit the MainNavigation.module.scss and do a little bit of work there. If you look that the MainNavigation, you will see that the contents in there are too cramped, there's no breathing space. So, I am going to first of all change the padding to: padding: 2rem 10%; for the entire container, remember it was padding: 0 10%; initially. This will give breathing room at the top and bottom of the container.

Then, the nav ul I will put a gap between its content: gap: 2rem; This will create space around the li(s). I will also add a hover effect on the li(s), so when we hover on them they change color from white to yellow and its cursor would be pointer.

So the Scss code will look something like this:

.main-nav-container{
    width: 100%;
    height: 5%;
    background-color: purple;
    padding: 2rem 10%;
    display: flex;
    align-items: center;
    justify-content: space-between;

    h2{
        color: white;
    }

     nav ul{
        display: flex;
        align-items: center;
        padding: 0;
        list-style: none;
        margin: 0;
        gap: 2rem;

        li{
            color: white;
        }
        li:hover{
            cursor: pointer;
            color: yellow;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now our MainNav should look like this:

Image ok
Beautiful

ACT 4:PART FOUR:
Here comes the react-router:
Integrating React Router for Navigation

Alright, let's get cracking. I will setup the router by going to App.tsx file then write out this code:

import {Routes,Route}from "react-router-dom";
Enter fullscreen mode Exit fullscreen mode

There I am importing Routes and Route from the react-router-dom package.
I will also go to the main.tsx file and write out this line of code:

import { BrowserRouter } from "react-router-dom";
Enter fullscreen mode Exit fullscreen mode

Then allow BrowserRouter to serve as the over all parent to our App. That way, it monitors the entire application, and makes it possible for us to switch between components.
The code in the main.tsx file would look like this:

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
import { BrowserRouter } from "react-router-dom";

createRoot(document.getElementById("root")!).render(
  <BrowserRouter>
    <StrictMode>
      <App />
    </StrictMode>
  </BrowserRouter>
);
Enter fullscreen mode Exit fullscreen mode

Explaining The Routes and Route in App.tsx:
Then Back to our App.tsx file, in order to setup out Routes and Route in the App.tsx file, I will write my codes this way:

function App() {
  return (
    <Layout>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/images-flex" element={<ImagesFlex />} />
        <Route path="/images-grid" element={<ImagesGrid />} />
      </Routes>
    </Layout>
  )
}
export default App
Enter fullscreen mode Exit fullscreen mode

Now let me explain. In the code above Routes is serving as a wrapper that tells React Router the routes or pages that are in our App. And the Routes that are present in our Application are 3. They are Home, ImagesFlex, ImagesGrid. And I must add that each route up there stands for a single page.

Also, you will notice that each route has 2 attributes. The path and element attribute.

path: This is the url that our web browser would recognize.

element: This attribute holds the component that would be rendered
when
a user navigates to the corresponding path.
To make it abit clearer, if I go to the path of /, the component that
displays is going to be Home. And this /, is known as the root path for
our app.

ACT 4:PART FIVE:
Styling NavLink in MainNavigation:

I am going back to the MainNavigation.tsx file, I will be making some changes there.
I have made some changes to the MainNavigation file and it looks like this now:

const MainNavigation = () => {

  const navDataHandler = (navData: any) => {
    return navData.isActive ? classes.active : "";
  };

  return (
    <div className={classes["main-nav-container"]}>
      <h2>
        <NavLink to={"/"} className={navDataHandler}>
          React Image
        </NavLink>
      </h2>

      <nav>
        <ul>
          <li>
            <NavLink to={"/images-flex"} className={navDataHandler}>
              images-flex
            </NavLink>
          </li>
          <li>
            <NavLink to={"/images-grid"} className={navDataHandler}>
              images-grid
            </NavLink>
          </li>
        </ul>
      </nav>
    </div>
  );
};

export default MainNavigation;
Enter fullscreen mode Exit fullscreen mode

NavLink:
So, I imported NavLink from react-router-dom. It works in a way that is similar to an (a) tag in normal Html. One of its features is that it can tell if a link is active or not.

navDataHandler:
This is a helper function used to style the NavLink that is active. It uses a ternery operator condition to carry it out. If a NavLink is active it will apply a css class of active to it. And if it is not active, it will leave it blank.
The navDataHandler takes a parameter which is going to be an object provided by NavLink, which will contain details about the link state.

Putting it all together:
When a user clicks on a link in the MainNavigation, for example /ImagesFlex, the NavLink pointing to /ImagesFlex will call navDataHandler to check if it is active. If it is active, it will return class.active. The other NavLinks won't get the classes.active.

Outro:

About the writer: Voke Bernard is a passionate {obsessive} and ambitious M.E.R.N developer. Building of Reactjs && Expressjs applications is all he does. He is currently open to work, Feel free to reach out.

Call to Action: If you enjoyed this act, stay tuned. ACT 5 follows shortly.

Top comments (0)