Skip to content

Commit

Permalink
Merge branch 'canary' into canary
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseKoldewijn authored Jan 19, 2024
2 parents 3fbaeba + 4f07843 commit b6eaa6a
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 49 deletions.
2 changes: 1 addition & 1 deletion docs/01-getting-started/02-project-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ This page provides an overview of the file and folder structure of a Next.js pro

| | |
| ---------------------------------------------------------------------------------------------- | -------------------------- |
| [`@folder`](/docs/app/building-your-application/routing/parallel-routes#convention) | Named slot |
| [`@folder`](/docs/app/building-your-application/routing/parallel-routes#slots) | Named slot |
| [`(.)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | Intercept same level |
| [`(..)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | Intercept one level above |
| [`(..)(..)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | Intercept two levels above |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
---
title: Parallel Routes
description: Simultaneously render one or more pages in the same view that can be navigated independently. A pattern for highly dynamic applications.
related:
links:
- app/api-reference/file-conventions/default
---

Parallel Routing allows you to simultaneously or conditionally render one or more pages in the same layout. For highly dynamic sections of an app, such as dashboards and feeds on social sites, Parallel Routing can be used to implement complex routing patterns.
Parallel Routes allows you to simultaneously or conditionally render one or more pages within the same layout. They are useful for highly dynamic sections of an app, such as dashboards and feeds on social sites.

For example, you can simultaneously render the team and analytics pages.
For example, considering a dashboard, you can use parallel routes to simultaneously render the `team` and `analytics` pages:

<Image
alt="Parallel Routes Diagram"
Expand All @@ -15,33 +18,9 @@ For example, you can simultaneously render the team and analytics pages.
height="952"
/>

Parallel Routing allows you to define independent error and loading states for each route as they're being streamed in independently.
## Slots

<Image
alt="Parallel routes enable custom error and loading states"
srcLight="/docs/light/parallel-routes-cinematic-universe.png"
srcDark="/docs/dark/parallel-routes-cinematic-universe.png"
width="1600"
height="1218"
/>

Parallel Routing also allows you to conditionally render a slot based on certain conditions, such as authentication state. This enables fully separated code on the same URL.

<Image
alt="Conditional routes diagram"
srcLight="/docs/light/conditional-routes-ui.png"
srcDark="/docs/dark/conditional-routes-ui.png"
width="1600"
height="898"
/>

## Convention

Parallel routes are created using named **slots**. Slots are defined with the `@folder` convention, and are passed to the same-level layout as props.

> Slots are _not_ route segments and _do not affect the URL structure_. The file path `/@team/members` would be accessible at `/members`.
For example, the following file structure defines two explicit slots: `@analytics` and `@team`.
Parallel routes are created using named **slots**. Slots are defined with the `@folder` convention. For example, the following file structure defines two slots: `@analytics` and `@team`:

<Image
alt="Parallel Routes File-system Structure"
Expand All @@ -51,7 +30,7 @@ For example, the following file structure defines two explicit slots: `@analytic
height="687"
/>

The folder structure above means that the component in `app/layout.js` now accepts the `@analytics` and `@team` slots props, and can render them in parallel alongside the `children` prop:
Slots are passed as props to the shared parent layout. For the example above, the component in `app/layout.js` now accepts the `@analytics` and `@team` slots props, and can render them in parallel alongside the `children` prop:

```tsx filename="app/layout.tsx" switcher
export default function Layout(props: {
Expand Down Expand Up @@ -81,19 +60,28 @@ export default function Layout(props) {
}
```

> **Good to know**: The `children` prop is an implicit slot that does not need to be mapped to a folder. This means `app/page.js` is equivalent to `app/@children/page.js`.
However, slots are **not** [route segments](/docs/app/building-your-application/routing#route-segments) and do not affect the URL structure. For example, for `/dashboard/@analytics/views`, the URL will be `/dashboard/views` since `@analytics` is a slot.

> **Good to know**:
>
> - The `children` prop is an implicit slot that does not need to be mapped to a folder. This means `app/page.js` is equivalent to `app/@children/page.js`.
## Active state and navigation

## Unmatched Routes
By default, Next.js keeps track of the active _state_ (or subpage) for each slot. However, the content rendered within a slot will depend on the type of navigation:

By default, the content rendered within a slot will match the current URL.
- [**Soft Navigation**](/docs/app/building-your-application/routing/linking-and-navigating#5-soft-navigation): During client-side navigation, Next.js will perform a [partial render](/docs/app/building-your-application/routing/linking-and-navigating#4-partial-rendering), changing the subpage within the slot, while maintaining the other slot's active subpages, even if they don't match the current URL.
- **Hard Navigation**: After a full-page load (browser refresh), Next.js cannot determine the active state of slots that don't match the current URL. Instead, it will render a [`default.js`](#defaultjs) file for the unmatched slots, or `404` if `default.js` doesn't exist.

In the case of an unmatched slot, the content that Next.js renders differs based on the routing technique and folder structure.
> **Good to know**:
>
> - The `404` for unmatched routes helps ensure that you don't accidentally render a route that shouldn't be parallel rendered.
### `default.js`

You can define a `default.js` file to render as a fallback when Next.js cannot recover a slot's active state based on the current URL.
You can define a `default.js` file to render as a fallback for unmatched slots during the initial load or full-page reload.

Consider the following folder structure. The `@team` slot has a `settings` directory, but `@analytics` does not.
Consider the following folder structure. The `@team` slot has a `settings` page, but `@analytics` does not.

<Image
alt="Parallel Routes unmatched routes"
Expand All @@ -103,19 +91,15 @@ Consider the following folder structure. The `@team` slot has a `settings` direc
height="930"
/>

#### Navigation
When navigating to `/dashboard/settings`, the `@team` slot will render the `settings` page while maintaining the currently active page for the `@analytics` slot.

On navigation, Next.js will render the slot's previously active state, even if it doesn't match the current URL.
On refresh, Next.js will render a `default.js` for `@analytics`. If `default.js` doesn't exist, a `404` is rendered instead.

#### Reload
Additionally, since `children` is an implicit slot, you also need to create a `default.js` file to render a fallback for `children` when Next.js cannot recover the active state of the parent page.

On reload, Next.js will first try to render the unmatched slot's `default.js` file. If that's not available, a 404 gets rendered.
### `useSelectedLayoutSegment(s)`

> The 404 for unmatched routes helps ensure that you don't accidentally render a route that shouldn't be parallel rendered.
## `useSelectedLayoutSegment(s)`

Both [`useSelectedLayoutSegment`](/docs/app/api-reference/functions/use-selected-layout-segment) and [`useSelectedLayoutSegments`](/docs/app/api-reference/functions/use-selected-layout-segments) accept a `parallelRoutesKey`, which allows you to read the active route segment within that slot.
Both [`useSelectedLayoutSegment`](/docs/app/api-reference/functions/use-selected-layout-segment) and [`useSelectedLayoutSegments`](/docs/app/api-reference/functions/use-selected-layout-segments) accept a `parallelRoutesKey` parameter, which allows you to read the active route segment within a slot.

```tsx filename="app/layout.tsx" switcher
'use client'
Expand All @@ -142,7 +126,7 @@ export default function Layout(props) {
}
```

When a user navigates to `@auth/login`, or `/login` in the URL bar, `loginSegments` will be equal to the string `"login"`.
When a user navigates to `app/@auth/login` (or `/login` in the URL bar), `loginSegments` will be equal to the string `"login"`.

## Examples

Expand Down Expand Up @@ -291,6 +275,16 @@ export default function CatchAll() {
### Conditional Routes

Parallel Routes also allows you to conditionally render a slot based on certain conditions, such as authentication state. For example, you can render a `/dashboard` or `/login` page depending on whether the user is logged in:

<Image
alt="Conditional routes diagram"
srcLight="/docs/light/conditional-routes-ui.png"
srcDark="/docs/dark/conditional-routes-ui.png"
width="1600"
height="898"
/>

Parallel Routes can be used to implement conditional routing. For example, you can render a `@dashboard` or `@login` route depending on the authentication state.

```tsx filename="app/layout.tsx" switcher
Expand Down Expand Up @@ -324,3 +318,15 @@ export default function Layout({ dashboard, login }) {
width="1600"
height="898"
/>

### Streaming

Parallel Routes can be streamed independently, allowing you to define independent error and loading states for each route:

<Image
alt="Parallel routes enable custom error and loading states"
srcLight="/docs/light/parallel-routes-cinematic-universe.png"
srcDark="/docs/dark/parallel-routes-cinematic-universe.png"
width="1600"
height="1218"
/>
28 changes: 27 additions & 1 deletion docs/02-app/02-api-reference/02-file-conventions/default.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
---
title: default.js
description: API Reference for the default.js file.
related:
title: Learn more about Parallel Routes
links:
- app/building-your-application/routing/parallel-routes
---

This documentation is still being written. Please check back later.
The `default.js` file is used to render a fallback within [Parallel Routes](/docs/app/building-your-application/routing/parallel-routes) when Next.js cannot recover a [slot's](/docs/app/building-your-application/routing/parallel-routes#slots) active state after a full-page load.

During [soft navigation](/docs/app/building-your-application/routing/linking-and-navigating#5-soft-navigation), Next.js keeps track of the active _state_ (subpage) for each slot. However, for hard navigations (full-page load), Next.js cannot recover the active state. In this case, a `default.js` file can be rendered for subpages that don't match the current URL.

Consider the following folder structure. The `@team` slot has a `settings` page, but `@analytics` does not.

<Image
alt="Parallel Routes unmatched routes"
srcLight="/docs/light/parallel-routes-unmatched-routes.png"
srcDark="/docs/dark/parallel-routes-unmatched-routes.png"
width="1600"
height="930"
/>

When navigating to `/dashboard/settings`, the `@team` slot will render the `settings` page while maintaining the currently active page for the `@analytics` slot.

On refresh, Next.js will render a `default.js` for `@analytics`. If `default.js` doesn't exist, a `404` is rendered instead.

Additionally, since `children` is an implicit slot, you also need to create a `default.js` file to render a fallback for `children` when Next.js cannot recover the active state of the parent page.

## Props

`default.js` does not receive any props.
26 changes: 24 additions & 2 deletions errors/missing-suspense-with-csr-bailout.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Missing Suspense with CSR Bailout
title: Missing Suspense boundary with useSearchParams
---

#### Why This Error Occurred
Expand All @@ -10,7 +10,29 @@ Reading search parameters through `useSearchParams()` without a Suspense boundar

Ensure that calls to `useSearchParams()` are wrapped in a Suspense boundary.

```jsx title="app/search.js"
```tsx filename="app/search.tsx" switcher
'use client'

import { useSearchParams } from 'next/navigation'
import { Suspense } from 'react'

function Search() {
const searchParams = useSearchParams()

return <input placeholder="Search..." />
}

export function Searchbar() {
return (
// You could have a loading skeleton as the `fallback` too
<Suspense>
<Search />
</Suspense>
)
}
```

```jsx filename="app/search.js" switcher
'use client'

import { useSearchParams } from 'next/navigation'
Expand Down

0 comments on commit b6eaa6a

Please sign in to comment.