Defining routes by using predefined paths is not always enough for complex applications. In Next.js you can add brackets to a page (`[param]`) to create a dynamic route (a.k.a. url slugs, pretty urls, and others).
Consider the following page `pages/post/[pid].js`:
```jsx
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { pid } = router.query
return <p>Post: {pid}</p>
}
export default Post
```
Any route like `/post/1`, `/post/abc`, etc. will be matched by `pages/post/[pid].js`. The matched path parameter will be sent as a query parameter to the page, and it will be merged with the other query parameters.
For example, the route `/post/abc` will have the following `query` object:
```json
{ "pid": "abc" }
```
Similarly, the route `/post/abc?foo=bar` will have the following `query` object:
```json
{ "foo": "bar", "pid": "abc" }
```
However, route parameters will override query parameters with the same name. For example, the route `/post/abc?pid=123` will have the following `query` object:
Multiple dynamic route segments work the same way. The page `pages/post/[pid]/[comment].js` will match the route `/post/abc/a-comment` and its `query` object will be:
Client-side navigations to dynamic routes are handled with [`next/link`](/docs/api-reference/next/link.md). If we wanted to have links to the routes used above it will look like this:
```jsx
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Linkhref="/post/abc">
<a>Go to pages/post/[pid].js</a>
</Link>
</li>
<li>
<Linkhref="/post/abc?foo=bar">
<a>Also goes to pages/post/[pid].js</a>
</Link>
</li>
<li>
<Linkhref="/post/abc/a-comment">
<a>Go to pages/post/[pid]/[comment].js</a>
</Link>
</li>
</ul>
)
}
export default Home
```
Read our docs for [Linking between pages](/docs/routing/introduction.md#linking-between-pages) to learn more.
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:
The main difference between catch all and optional catch all routes is that with optional, the route without the parameter is also matched (`/post` in the example above).
- Pages that are statically optimized by [Automatic Static Optimization](/docs/advanced-features/automatic-static-optimization.md) will be hydrated without their route parameters provided, i.e `query` will be an empty object (`{}`).
After hydration, Next.js will trigger an update to your application to provide the route parameters in the `query` object.