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 theBrowserRouter
wrapped around your App anymore because you are already using its instance (createBrowserRouter
) in yourApp.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.