How to avoid redundancy through the use of  Layout Components in React

How to avoid redundancy through the use of Layout Components in React

I recently discovered that I had no idea what a layout component was. This occurred when I had to pull a team member's code and discovered that she didn't import the header and footer components into every component that required them. Layout components make it simple and efficient to avoid reusing components on different pages. As an example, consider a landing page. Rather than importing the header and footer components into your Home, About, and Contact pages, you can simply create a layout component that wraps the navbar and footer components around every component that will use them. This article will show you how to create and use a layout component to make your code more readable and easier to write. Stay tuned!

Structuring your src folder

To get started, let's create a React app. We'll use Vite because it saves a lot of time. I wrote an article on using Vite to create a React app; check it out here.

In your src folder, create three folders namely: components, layouts, and routes. In the component folder, create a footer and header file. In the layout folder, create a file and name it LandingPageLayout. In the routes folder, create an about and home file.

Your src folder should look like the screenshot below:

Instead of...

Before I learned about layout components, I used to import the header and footer components into any component that required them, as shown in the code snippet below.

import React from 'react'
import Footer from '../components/Footer'
import Header from '../components/Header'

const AboutUs = () => {
  return (
    <div>
      <Header />
      <p>About Us</p>
      <Footer />
    </div>
  )
}

export default AboutUs

But, there's a better and cleaner way to do it.

The createBrowserRouter function

Copy and paste the code snippet below into your App.js and I'll explain what it does.

import './App.css'
import { createBrowserRouter } from 'react-router-dom'
import { RouterProvider } from 'react-router'
import LandingPageLayout from './layouts/LandingPageLayout'
import Home from './routes/Home'
import AboutUs from './routes/AboutUs'
import './style/All.css'

const router = createBrowserRouter([
  {
    path: '/',
    element: <LandingPageLayout />,
    children: [
      {
        path: '/',
        element: <Home />,
      },
      {
        path: '/AboutUs',
        element: <AboutUs />,
      },
    ],
  },
])

export const App = () => <RouterProvider router={router} />

The function createBrowserRouter in the above snippet accepts an array of objects containing a set of routes that define how an application should handle different URL paths.

In our App.js, we have only one route object which has three properties which are path, element and children.

The path property specifies the URL that will be matched when that route is used, which in this case is set to the root application '/'.

The element property specifies the component that will be rendered when its route is used, which in this case is set to LandingPageLayout. This means that when the path ('/') is used, the contents of LandingPageLayout is rendered.

The children property contains an array of objects that define child routes.

There are two child routes in this case, as shown below:

children: [
      {
        path: '/',
        element: <Home />,
      },
      {
        path: '/AboutUs',
        element: <AboutUs />,
      },
    ],

ps: In your main.jsx, you don't need the BrowserRouter wrapped around your App anymore because you are already using its instance (createBrowserRouter) in your App.jsx.

Creating a Layout component

Copy and paste the following code into your LandingPageLayout:

import React from 'react'
import { Outlet } from 'react-router'
import Footer from '../components/Footer'
import Header from '../components/Header'

const LandingPageLayout = () => {
  return (
    <div>
      <Header />
        <Outlet />
      <Footer />
    </div>
  )
}

export default LandingPageLayout

The LandingPageLayout is the only component we would place our footer and header components in. We are doing this so as to avoid redundancy.

The role of an outlet component is to render the child route components of a given route. In this case, the outlet component renders the child route component of LandingPageLayout which is the home and about pages.

Add the following code to your header component:

import React from 'react'
import { Link } from 'react-router-dom'

const Header = () => {
  return (
    <div className='navbar'>
      <Link to='/'>
        <h4>Home</h4>
      </Link>
      <Link to='/AboutUs'>
        <h4 className='About-text'>About</h4>
      </Link>
    </div>
  )
}

export default Header

In your browser, you'll see something like the screenshot below:

From the screenshot above, you can see that we have a header that consists of "home" and "about," and a footer whose only content is "footer." From the header, you can navigate to the about page, which also shares the header and footer content.