rsnext/docs/api-reference/next/router.md
Luis Alvarez D e3465615e4 New docs (#9301)
* Added the docs from Notion

* Updated the links from notion to relative links

* Added a routes manifest to the docs

* Removed the <br> after examples toggle

* Use the name of the section instead of Introduction

* Fixed spelling errors

* Optimize the content for Algolia

* Add a paragraph for `pageProps`

* Add welcome section

* Transpile -> Compile

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Test extra room between

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update getting-started.md

* Update manifest.json

* Update getting-started.md

* Update getting-started.md

* Add concepts section

* Update pages.md

* Update pages.md

* Add data fetching section

* Update pages.md

* See how a card looks like

* Undo card changes

* Added related section to getting-started

* Fixed wrong markdown syntax in the withRouter page

* Moved the server-side-and-client-side section

* Updated next-cli reference

* updated getInitialProps section

* Minor fixes

* Added more Related sections

* Add html to the related section in getting-started

* Use small for the card

* Use cards for all related sections

* Added src directory docs

* Added src directory to the manifest

* Add note about API routes in next export

* Add initial data fetching docs (private until new methods are released)

* Fix typos

* Improve wording

* Update getting-started.md

* Update getting-started.md

* Move advanced concepts to advanced section

* Hide server-side vs client-side

* Move AMP support

* Move typescript into one page

* Add routing concepts page

* Remove introduction page

* Update section on different route types

* Update routing.md

* Update routing.md

* Update routing.md

* Update routing.md

* Combine router injection pages

* Update pages.md

* Update routing.md

* Update using-link.md

* Update using-link.md

* Update typescript.md

* Move the API Routes typescript to basic features

* Added links to the typescript section

* Updated links to useRouter and withRouter

* Add singleLevel prop to manifest

* Added single page for router docs

* Updated description

* Updated the routes in the manifest

* Add data fetching section

* Update data-fetching.md

* Update data-fetching.md

* Update dynamic-routes.md

* Update manifest.json

* Only use the single router API page

* Moved the concepts pages

* Updated links

* Removed extra space

* Updated title for Router API

* Added a description with frontmatter

* Add open prop to the manifest

* Added datafetching section to API Reference

* Updated links to the getInitialProps reference

* Moved some sections to API

* Added next/head to API reference

* Added next/link to the API Reference

* Removed the populating-head section

* Updated links to the new next/link API

* Added link from dynamic-routes to next/link docs

* use a paragraph

* Added next/router API

* Added next/amp

* Updated the docs for next/amp

* Moved the AMP support folder

* Updated title

* Content updates

* Added more links to the data fetching section

* Added links from the API to introductions

* changing the router API

* Updates to the router API

* Updated the routing section

* life improvements

* Added shallow routing section

* Small fix

* Removed old routing sections

* Updated link to shallow routing

* Removed unrequired page

* Removed /pages

* Update data-fetching.md

* Add initial deployments section

* Update manifest.json

* Update introduction.md

* Update deployment doc

* Add static export section updates

* link ssg/ssr

* Update deployment.md

* Add syntax highlighting

Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
2019-12-23 16:07:38 +01:00

8 KiB

next/router

Before moving forward, we recommend you to read Routing Introduction first.

useRouter

If you want to access the router object inside any function component in your app, you can use the useRouter hook, take a look at the following example:

import { useRouter } from 'next/router'

function ActiveLink({ children, href }) {
  const router = useRouter()
  const style = {
    marginRight: 10,
    color: router.pathname === href ? 'red' : 'black',
  }

  const handleClick = e => {
    e.preventDefault()
    router.push(href)
  }

  return (
    <a href={href} onClick={handleClick} style={style}>
      {children}
    </a>
  )
}

export default ActiveLink

useRouter is a React Hook, meaning it cannot be used with classes. You can either use withRouter or wrap your class in a function component.

router object

The following is the definition of the router object returned by both useRouter and withRouter:

  • route: String - Current route
  • pathname: String - Current path excluding the query string
  • query: Object - The query string parsed to an object. Defaults to {}
  • asPath: String - Actual path (including the query) shown in the browser

Additionally, the Router API is also included inside the object.

The query object will be empty during prerendering if the page is statically optimized.

withRouter

If useRouter is not the best fit for you, withRouter can also add the same router object to any component, here's how to use it:

import { withRouter } from 'next/router'

function Page({ router }) {
  return <p>{router.pathname}</p>
}

export default withRouter(Page)

Router API

The API of Router, exported by next/router, is defined below.

Router.push

Examples

Handles client-side transitions, this method is useful for cases where next/link is not enough.

import Router from 'next/router'

Router.push(url, as, options)
  • url - The URL to navigate to. This is usually the name of a page
  • as - Optional decorator for the URL that will be shown in the browser. Defaults to url
  • options - Optional object with the following configuration options:
    • shallow: Update the path of the current page without rerunning getInitialProps. Defaults to false

You don't need to use Router for external URLs, window.location is better suited for those cases.

Usage

Navigating to pages/about.js, which is a predefined route:

import Router from 'next/router'

function Page() {
  return <span onClick={() => Router.push('/about')}>Click me</span>
}

Navigating pages/post/[pid].js, which is a dynamic route:

import Router from 'next/router'

function Page() {
  return (
    <span onClick={() => Router.push('/post/[pid]', '/post/abc')}>
      Click me
    </span>
  )
}

With URL object

You can use an URL object in the same way you can use it for next/link. Works for both the url and as parameters:

import Router from 'next/router'

const handler = () => {
  Router.push({
    pathname: '/about',
    query: { name: 'Zeit' },
  })
}

function ReadMore() {
  return (
    <div>
      Click <span onClick={handler}>here</span> to read more
    </div>
  )
}

export default ReadMore

Router.replace

Similar to the replace prop in next/link, Router.replace will prevent adding a new URL entry into the history stack, take a look at the following example:

import Router from 'next/router'

Router.replace('/home')

The API for Router.replace is exactly the same as that used for Router.push.

Router.beforePopState

In some cases (for example, if using a Custom Server), you may wish to listen to popstate and do something before the router acts on it.

You could use this to manipulate the request, or force a SSR refresh, as in the following example:

import Router from 'next/router'

Router.beforePopState(({ url, as, options }) => {
  // I only want to allow these two routes!
  if (as !== '/' && as !== '/other') {
    // Have SSR render bad routes as a 404.
    window.location.href = as
    return false
  }

  return true
})

Router.beforePopState(cb: () => boolean)

  • cb - The function to execute on incoming popstate events. The function receives the state of the event as an object with the following props:
    • url: String - the route for the new state. This is usually the name of a page
    • as: String - the url that will be shown in the browser
    • options: Object - Additional options sent by Router.push

If the function you pass into beforePopState returns false, Router will not handle popstate and you'll be responsible for handling it, in that case. See Disabling file-system routing.

Router.events

Examples

You can listen to different events happening inside the Router. Here's a list of supported events:

  • routeChangeStart(url) - Fires when a route starts to change
  • routeChangeComplete(url) - Fires when a route changed completely
  • routeChangeError(err, url) - Fires when there's an error when changing routes, or a route load is cancelled
    • err.cancelled - Indicates if the navigation was cancelled
  • beforeHistoryChange(url) - Fires just before changing the browser's history
  • hashChangeStart(url) - Fires when the hash will change but not the page
  • hashChangeComplete(url) - Fires when the hash has changed but not the page

Here url is the URL shown in the browser. If you call Router.push(url, as) (or similar), then the value of url will be as.

For example, to listen to the router event routeChangeStart, do the following:

import Router from 'router/events'

const handleRouteChange = url => {
  console.log('App is changing to: ', url)
}

Router.events.on('routeChangeStart', handleRouteChange)

If you no longer want to listen to the event, unsubscribe with the off method:

import Router from 'router/events'

Router.events.off('routeChangeStart', handleRouteChange)

If a route load is cancelled (for example, by clicking two links rapidly in succession), routeChangeError will fire. And the passed err will contain a cancelled property set to true, as in the following example:

import Router from 'router/events'

Router.events.on('routeChangeError', (err, url) => {
  if (err.cancelled) {
    console.log(`Route to ${url} was cancelled!`)
  }
})

Router events should be registered when a component mounts (useEffect or componentDidMount / componentWillUnmount) or imperatively when an event happens, as in the following example:

import Router from 'router/events'

useEffect(() => {
  const handleRouteChange = url => {
    console.log('App is changing to: ', url)
  }

  Router.events.on('routeChangeStart', handleRouteChange)
  return () => {
    Router.events.off('routeChangeStart', handleRouteChange)
  }
}, [])