Files
0ab8c20978 docs: Make a better sentence by connecting with comma (#63355)
This PR makes a grammatical improvement for a sentence in the
documentations page
(https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts)

Co-authored-by: Sam Ko <[email protected]>
2024-03-17 19:35:55 +00:00

270 lines
11 KiB
Plaintext

---
title: Pages and Layouts
description: Create your first page and shared layout with the App Router.
---
> We recommend reading the [Routing Fundamentals](/docs/app/building-your-application/routing) and [Defining Routes](/docs/app/building-your-application/routing/defining-routes) pages before continuing.
The special files [layout.js](#layouts), [page.js](#pages), and [template.js](#templates) allow you to create UI for a [route](/docs/app/building-your-application/routing/defining-routes#creating-routes). This page will guide you through how and when to use these special files.
## Pages
A page is UI that is **unique** to a route. You can define a page by default exporting a component from a `page.js` file.
For example, to create your `index` page, add the `page.js` file inside the `app` directory:
<Image
alt="page.js special file"
srcLight="/docs/light/page-special-file.png"
srcDark="/docs/dark/page-special-file.png"
width="1600"
height="444"
/>
```tsx filename="app/page.tsx" switcher
// `app/page.tsx` is the UI for the `/` URL
export default function Page() {
return <h1>Hello, Home page!</h1>
}
```
```jsx filename="app/page.js" switcher
// `app/page.js` is the UI for the `/` URL
export default function Page() {
return <h1>Hello, Home page!</h1>
}
```
Then, to create further pages, create a new folder and add the `page.js` file inside it. For example, to create a page for the `/dashboard` route, create a new folder called `dashboard`, and add the `page.js` file inside it:
```tsx filename="app/dashboard/page.tsx" switcher
// `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}
```
```jsx filename="app/dashboard/page.js" switcher
// `app/dashboard/page.js` is the UI for the `/dashboard` URL
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}
```
> **Good to know**:
>
> - The `.js`, `.jsx`, or `.tsx` file extensions can be used for Pages.
> - A page is always the [leaf](/docs/app/building-your-application/routing#terminology) of the [route subtree](/docs/app/building-your-application/routing#terminology).
> - A `page.js` file is required to make a route segment publicly accessible.
> - Pages are [Server Components](/docs/app/building-your-application/rendering/server-components) by default, but can be set to a [Client Component](/docs/app/building-your-application/rendering/client-components).
> - Pages can fetch data. View the [Data Fetching](/docs/app/building-your-application/data-fetching) section for more information.
## Layouts
A layout is UI that is **shared** between multiple routes. On navigation, layouts preserve state, remain interactive, and do not re-render. Layouts can also be [nested](#nesting-layouts).
You can define a layout by default exporting a React component from a `layout.js` file. The component should accept a `children` prop that will be populated with a child layout (if it exists) or a page during rendering.
For example, the layout will be shared with the `/dashboard` and `/dashboard/settings` pages:
<Image
alt="layout.js special file"
srcLight="/docs/light/layout-special-file.png"
srcDark="/docs/dark/layout-special-file.png"
width="1600"
height="606"
/>
```tsx filename="app/dashboard/layout.tsx" switcher
export default function DashboardLayout({
children, // will be a page or nested layout
}: {
children: React.ReactNode
}) {
return (
<section>
{/* Include shared UI here e.g. a header or sidebar */}
<nav></nav>
{children}
</section>
)
}
```
```jsx filename="app/dashboard/layout.js" switcher
export default function DashboardLayout({
children, // will be a page or nested layout
}) {
return (
<section>
{/* Include shared UI here e.g. a header or sidebar */}
<nav></nav>
{children}
</section>
)
}
```
### Root Layout (Required)
The root layout is defined at the top level of the `app` directory and applies to all routes. This layout is **required** and must contain `html` and `body` tags, allowing you to modify the initial HTML returned from the server.
```tsx filename="app/layout.tsx" switcher
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* Layout UI */}
<main>{children}</main>
</body>
</html>
)
}
```
```jsx filename="app/layout.js" switcher
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{/* Layout UI */}
<main>{children}</main>
</body>
</html>
)
}
```
### Nesting Layouts
By default, layouts in the folder hierarchy are **nested**, which means they wrap child layouts via their `children` prop. You can nest layouts by adding `layout.js` inside specific route segments (folders).
For example, to create a layout for the `/dashboard` route, add a new `layout.js` file inside the `dashboard` folder:
<Image
alt="Nested Layout"
srcLight="/docs/light/nested-layout.png"
srcDark="/docs/dark/nested-layout.png"
width="1600"
height="606"
/>
```tsx filename="app/dashboard/layout.tsx" switcher
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
```
```jsx filename="app/dashboard/layout.js" switcher
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
```
If you were to combine the two layouts above, the root layout (`app/layout.js`) would wrap the dashboard layout (`app/dashboard/layout.js`), which would wrap route segments inside `app/dashboard/*`.
The two layouts would be nested as such:
<Image
alt="Nested Layouts"
srcLight="/docs/light/nested-layouts-ui.png"
srcDark="/docs/dark/nested-layouts-ui.png"
width="1600"
height="1026"
/>
> **Good to know**:
>
> - `.js`, `.jsx`, or `.tsx` file extensions can be used for Layouts.
> - Only the root layout can contain `<html>` and `<body>` tags.
> - When a `layout.js` and `page.js` file are defined in the same folder, the layout will wrap the page.
> - Layouts are [Server Components](/docs/app/building-your-application/rendering/server-components) by default but can be set to a [Client Component](/docs/app/building-your-application/rendering/client-components).
> - Layouts can fetch data. View the [Data Fetching](/docs/app/building-your-application/data-fetching) section for more information.
> - Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will [automatically dedupe the requests](/docs/app/building-your-application/caching#request-memoization) without affecting performance.
> - Layouts do not have access to the route segments below itself. To access all route segments, you can use [`useSelectedLayoutSegment`](/docs/app/api-reference/functions/use-selected-layout-segment) or [`useSelectedLayoutSegments`](/docs/app/api-reference/functions/use-selected-layout-segments) in a Client Component.
> - You can use [Route Groups](/docs/app/building-your-application/routing/route-groups) to opt specific route segments in and out of shared layouts.
> - You can use [Route Groups](/docs/app/building-your-application/routing/route-groups) to create multiple root layouts. See an [example here](/docs/app/building-your-application/routing/route-groups#creating-multiple-root-layouts).
> - **Migrating from the `pages` directory:** The root layout replaces the [`_app.js`](/docs/pages/building-your-application/routing/custom-app) and [`_document.js`](/docs/pages/building-your-application/routing/custom-document) files. [View the migration guide](/docs/app/building-your-application/upgrading/app-router-migration#migrating-_documentjs-and-_appjs).
## Templates
Templates are similar to layouts in that they wrap each child layout or page. Unlike layouts that persist across routes and maintain state, templates create a new instance for each of their children on navigation. This means that when a user navigates between routes that share a template, a new instance of the component is mounted, DOM elements are recreated, state is **not** preserved, and effects are re-synchronized.
There may be cases where you need those specific behaviors, and templates would be a more suitable option than layouts. For example:
- Features that rely on `useEffect` (e.g logging page views) and `useState` (e.g a per-page feedback form).
- To change the default framework behavior. For example, Suspense Boundaries inside layouts only show the fallback the first time the Layout is loaded and not when switching pages. For templates, the fallback is shown on each navigation.
A template can be defined by exporting a default React component from a `template.js` file. The component should accept a `children` prop.
<Image
alt="template.js special file"
srcLight="/docs/light/template-special-file.png"
srcDark="/docs/dark/template-special-file.png"
width="1600"
height="444"
/>
```tsx filename="app/template.tsx" switcher
export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
```
```jsx filename="app/template.js" switcher
export default function Template({ children }) {
return <div>{children}</div>
}
```
In terms of nesting, `template.js` is rendered between a layout and its children. Here's a simplified output:
```jsx filename="Output"
<Layout>
{/* Note that the template is given a unique key. */}
<Template key={routeParam}>{children}</Template>
</Layout>
```
## Metadata
In the `app` directory, you can modify the `<head>` HTML elements such as `title` and `meta` using the [Metadata APIs](/docs/app/building-your-application/optimizing/metadata).
Metadata can be defined by exporting a [`metadata` object](/docs/app/api-reference/functions/generate-metadata#the-metadata-object) or [`generateMetadata` function](/docs/app/api-reference/functions/generate-metadata#generatemetadata-function) in a [`layout.js`](/docs/app/api-reference/file-conventions/layout) or [`page.js`](/docs/app/api-reference/file-conventions/page) file.
```tsx filename="app/page.tsx" switcher
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
```
```jsx filename="app/page.js" switcher
export const metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
```
> **Good to know**: You should **not** manually add `<head>` tags such as `<title>` and `<meta>` to root layouts. Instead, you should use the [Metadata API](/docs/app/api-reference/functions/generate-metadata) which automatically handles advanced requirements such as streaming and de-duplicating `<head>` elements.
Learn more about available metadata options in the [API reference](/docs/app/api-reference/functions/generate-metadata)