Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add catch all routes example and a link to it in docs #10202

Merged
merged 6 commits into from
Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/routing/dynamic-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,16 @@ Client-side navigations to a dynamic route can be handled with [`next/link`](/do

### Catch all routes

<details>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/catch-all-routes">Catch All Routes</a></li>
</ul>
</details>

Dynamic routes can be extended to catch all paths by adding three dots (`...`) inside the brackets. For example:

- `pages/post/[...slug]` matches `/post/a`, but also `post/a/b`, `post/a/b/c` and so on.
- `pages/post/[...slug].js` matches `/post/a`, but also `post/a/b`, `post/a/b/c` and so on.

Matched parameters will be sent as a query parameter (`slug` in the example) to the page, and it will always be an array, so, the path `/post/a` will have the following `query` object:

Expand Down
2 changes: 1 addition & 1 deletion docs/routing/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ To match a dynamic segment you can use the bracket syntax. This allows you to ma

- `pages/blog/[slug].js` → `/blog/:slug` (`/blog/hello-world`)
- `pages/[username]/settings.js` → `/:username/settings` (`/foo/settings`)
- `pages/post/[...all]` → `/post/*` (`/post/2020/id/title`)
- `pages/post/[...all].js` → `/post/*` (`/post/2020/id/title`)

## Linking between pages

Expand Down
55 changes: 55 additions & 0 deletions examples/catch-all-routes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Catch All Routes Example

This example shows how to use [Catch all routes](https://nextjs.org/docs/routing/dynamic-routes#catch-all-routes) in Next.js, which allows a dynamic route to catch all paths.

The catch all page is in `pages/post/[...slug]`, it matches any path after `/post`, like the following:

- `/post/first-post`,
- `/post/2020/first-post`
- `/post/2020/first-post/with/catch/all/routes`
- Anything that matches the glob `/post/*`
lfades marked this conversation as resolved.
Show resolved Hide resolved

You can use `next/link` as displayed in this example to route to these pages client side.

## Deploy your own

Deploy the example using [ZEIT Now](https://zeit.co/now):

[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/next.js/tree/canary/examples/catch-all-routes)

## How to use

### Using `create-next-app`

Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:

```bash
npm init next-app --example catch-all-routes catch-all-routes-app
# or
yarn create next-app --example catch-all-routes catch-all-routes-app
```

### Download manually

Download the example:

```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/catch-all-routes
cd catch-all-routes
```

Install it and run:

```bash
npm install
npm run dev
# or
yarn
yarn dev
```

Deploy it to the cloud with [Now](https://zeit.co/now) ([download](https://zeit.co/download)):

```bash
now
```
36 changes: 36 additions & 0 deletions examples/catch-all-routes/components/header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Link from 'next/link'

const Header = () => (
<header>
<ul>
<li>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li>
<Link href="/about">
<a>About</a>
</Link>
</li>
<li>
<Link
href="/post/[...slug]"
as="/post/2020/first-post/with/catch/all/routes"
>
<a>First Post</a>
</Link>
</li>
<li>
<Link
href="/post/[...slug]"
as="/post/2020/second-post/with/catch/all/routes"
>
<a>Second Post</a>
</Link>
</li>
</ul>
</header>
)

export default Header
15 changes: 15 additions & 0 deletions examples/catch-all-routes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "catch-all-routes",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"license": "ISC",
"dependencies": {
"next": "latest",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
10 changes: 10 additions & 0 deletions examples/catch-all-routes/pages/about.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Header from '../components/header'

const About = () => (
<>
<Header />
<h1>About page</h1>
</>
)

export default About
10 changes: 10 additions & 0 deletions examples/catch-all-routes/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Header from '../components/header'

const Home = () => (
<>
<Header />
<h1>Hello World!</h1>
</>
)

export default Home
16 changes: 16 additions & 0 deletions examples/catch-all-routes/pages/post/[...slug].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useRouter } from 'next/router'
import Header from '../../components/header'

const Comment = () => {
const router = useRouter()
const slug = router.query.slug || []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot be null:

Suggested change
const slug = router.query.slug || []
const slug = router.query.slug

Copy link
Member Author

@lfades lfades Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's null in the first render, I thought that was expected because it doesn't have data requirements 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I forgot about automatic static prerendering.


return (
<>
<Header />
<h1>Slug: {slug.join('/')}</h1>
</>
)
}

export default Comment
4 changes: 1 addition & 3 deletions examples/dynamic-routing/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Dynamic Routing example

This example shows usage of dynamic routing.

This example contains two dynamic pages:
This example shows how to do [dynamic routing](https://nextjs.org/docs/routing/dynamic-routes) in Next.js. It contains two dynamic routes:

1. `pages/post/[id]/index.js`
- e.g. matches `/post/my-example` (`/post/:id`)
Expand Down