Skip to content

Commit

Permalink
Docs: workarounds for router not resetting state (fixes vercel#35138)
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshfisher committed Mar 28, 2022
1 parent 0d401dd commit a94b977
Showing 1 changed file with 56 additions and 2 deletions.
58 changes: 56 additions & 2 deletions docs/api-reference/next/router.md
Expand Up @@ -113,8 +113,6 @@ export default function Page() {
}
```

> **Note:** When navigating to the same page in Next.js, the page's state **will not** be reset by default, as the top-level React component is the same. You can manually ensure the state is updated using `useEffect`.
Redirecting the user to `pages/login.js`, useful for pages behind [authentication](/docs/authentication):

```jsx
Expand All @@ -138,6 +136,62 @@ export default function Page() {
}
```

#### Resetting state after navigation

When navigating to the same page in Next.js, the page's state **will not** be reset by default:

```jsx
// pages/[pageTitle].jsx

import Link from "next/link"
import { useState } from "react"

export const getServerSideProps = async ({ params }) => ({
props: {
pageTitle: params["pageTitle"]
}
})

export default function Page({ pageTitle }) {
const [title] = useState(pageTitle)
return (
<div>
<h1>{title}</h1>
<Link href="/one">
<a>one</a>
</Link>{" "}
<Link href="/two">
<a>two</a>
</Link>
</div>
)
}
```

Above, navigating between `/foo` and `/bar` **will not** change the page title. The `useState` is initialized for the first `Page` component, and not re-initialized when navigating to a different `Page` instance. This is because the top-level React component, `Page`, is the same.

If you do not want this behavior, you have a couple of options:

1. Manually ensure each state is updated using `useEffect`. Above, that could look like:

```jsx
useEffect(() => {
setTitle(pageTitle)
}, [pageTitle])
```

2. Use a React `key` to [tell React to remount the component](https://kentcdodds.com/blog/understanding-reacts-key-prop#:~:text=This%20allows%20you%20to%20return%20the%20exact%20same%20element%20type%2C%20but%20force%20React%20to%20unmount%20the%20previous%20instance%2C%20and%20mount%20a%20new%20one.). To do this for all pages, you can use a custom app:

```jsx
// pages/_app.jsx
import { useRouter } from "next/router"

export default function MyApp({ Component, pageProps }) {
const router = useRouter()
return <Component key={router.asPath} {...pageProps} />
}
```

#### With URL object

You can use a URL object in the same way you can use it for [`next/link`](/docs/api-reference/next/link.md#with-url-object). Works for both the `url` and `as` parameters:
Expand Down

0 comments on commit a94b977

Please sign in to comment.