In Next.js, using layouts to wrap sub-routes (or nested routes) is an effective way to apply consistent structure and style across various components of your application. Since Next.js does not natively support route-based layouts in the way that frameworks like Nuxt.js do, this functionality must be implemented manually. Here’s a straightforward way to achieve this using React components and Next.js’s file system routing.
Step 1: Define a Layout Component
A layout component is a React component that includes the common UI parts of your pages (e.g., header, footer, navbars). You can create multiple layouts for different parts of your app if needed.
Example Layout Component
Create a file named MainLayout.js
in a components
directory:
jsxCopy code
import React from 'react'; import Header from './Header'; import Footer from './Footer'; const MainLayout = ({ children }) => { return ( <div> <Header /> <main>{children}</main> <Footer /> </div> ); }; export default MainLayout;
This component includes a header and footer and a dynamic children
section where sub-components will be rendered.
Step 2: Use the Layout in Page Components
In Next.js, every file under the pages
directory (and subdirectories) corresponds to a route. To apply the layout, wrap the page’s content with the layout component.
Example Page Component Using MainLayout
Create a page profile.js
in the pages
directory:
jsxCopy code
import React from 'react'; import MainLayout from '../components/MainLayout'; const ProfilePage = () => { return ( <MainLayout> <h1>Profile Page</h1> <p>This is the profile page content.</p> </MainLayout> ); }; export default ProfilePage;
This setup uses the MainLayout
for the profile page. You can apply the same layout to other pages or define new layouts for different sections of your application.
Step 3: Using Layouts for Nested Routes
If you have nested routes and want to use layouts, the approach is similar but organized differently. Suppose you have user settings pages under /user/settings
with multiple sub-pages.
Organizing Nested Routes with a Specific Layout
- Create a Subdirectory for Nested Routes:Inside the
pages
directory, create a subdirectory for the main route:markdownCopy codepages/ ├── user/ └── settings/ ├── index.js ├── password.js ├── profile.js
- Apply Layout to Nested Routes:Each page inside the
settings
directory can use theMainLayout
or another specific layout likeSettingsLayout
.jsxCopy code// pages/user/settings/profile.js import React from 'react'; import MainLayout from '../../../components/MainLayout'; const SettingsProfilePage = () => { return ( <MainLayout> <h1>Settings: Profile</h1> <p>Change your profile settings here.</p> </MainLayout> ); }; export default SettingsProfilePage;
Using a Global Layout with a Condition for Specific Pages
To apply a global layout or specific layouts based on routes conditionally:
- Create a
_app.js
File:This is where you can wrap your application in a global layout.jsxCopy code// pages/_app.js import React from 'react'; import MainLayout from '../components/MainLayout'; import App from 'next/app'; class MyApp extends App { render() { const { Component, pageProps } = this.props; return ( <MainLayout> <Component {...pageProps} /> </MainLayout> ); } } export default MyApp;
- Conditionally Change Layouts:If you need different layouts for different parts of your app, you can modify
_app.js
to include logic that selects a layout based on the pathname.jsxCopy code// pages/_app.js import React from 'react'; import MainLayout from '../components/MainLayout'; import AnotherLayout from '../components/AnotherLayout'; import App, { Container } from 'next/app'; import { useRouter } from 'next/router'; function MyApp({ Component, pageProps }) { const router = useRouter(); const getLayout = Component.getLayout || ((page) => <MainLayout>{page}</MainLayout>); return getLayout(<Component {...pageProps} />); } export default MyApp;
In your page components:jsxCopy code// pages/someSpecialPage.js const SomeSpecialPage = () => <div>Special Content Here</div>; SomeSpecialPage.getLayout = function getLayout(page) { return ( <AnotherLayout> {page} </AnotherLayout> ); } export default SomeSpecialPage;
This setup offers flexibility, allowing you to specify which layout to use on a per-page basis while maintaining the ability to apply a default layout across the site. This is particularly useful for complex applications with varying UI requirements across different sections.