Next.js: Singleton access to router

Created on 17 Nov 2016  ยท  9Comments  ยท  Source: vercel/next.js

There should be a way to access the router instance globally.

Right now, if one wants to use a redirect from an action or event, we have to provide the router in the component's static contextTypes and redirect with this.context.router.push(null, 'page') (or pass the router to the redux action)

However, if we want to do redirects in redux actions or other helpers, it would be great to have a global access to this router instance. React-router solves this by using history.push() from the (browser)history package.

What would be the best way to implement this?

feature request

Most helpful comment

absolutely. I've been thinking we could do

import Link from 'next/link'
Link.go('/a')

as an alternative to this.props.url.pushTo('/a') for example

All 9 comments

absolutely. I've been thinking we could do

import Link from 'next/link'
Link.go('/a')

as an alternative to this.props.url.pushTo('/a') for example

I've created a quick PR for this (https://github.com/zeit/next.js/pull/275) but I'm sure there is a better solution.

Also, I think it makes more sense to put expose the Router and have the 'go' method on the router instead of the Link.

I also feel singleton router would be better.
Additionally, maybe we can also support onpopstate on it too for loading indicator (https://github.com/zeit/next.js/pull/250#issuecomment-261469041).

I am down with exposing a Router to the user too. It sounds better than Link. And I feel that's where this function belongs.

I have a working solution but I'm not happy with storing the current router's instance to window

(/lib/router.js)

export default class Router {
  constructor (url, initialData) {
    const parsed = parse(url, true)

    // represents the current component key
    this.route = toRoute(parsed.pathname)

    // set up the component cache (by route keys)
    this.components = { [this.route]: initialData }

    this.pathname = parsed.pathname
    this.query = parsed.query
    this.subscriptions = new Set()
    this.componentLoadCancel = null
    this.onPopState = this.onPopState.bind(this)

    if (typeof window !== 'undefined') {
      window.addEventListener('popstate', this.onPopState)
->    window.currentRouter = this // <---- save class instance
    }
  }

  /* expose method statically so we can use
      import Router from 'next/router'
      Router.go('/path') 
  */
  static go (href) {
    window.currentRouter.change('pushState', null, href)
  }

....

I've also tried saving the router as a variable in router.js but apparently you can't access those from the constructor. Any other suggestions?

@jonaswindey I think this is only way to fix it until we land a fix for #253

Ok, do I already create a PR for this so we can proceed?

We already expose next object to global on dev mode and you can access Router like next.router. I think we can just do it for production too.

https://github.com/zeit/next.js/blob/master/client/next-dev.js

Stats from current PR


Default Server Mode



General

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| buildDuration | 16.4s | 17.2s | โš ๏ธ +791ms |
| nodeModulesSize | 48.3 MB | 48.3 MB | โœ“ |


Client Bundles (main, webpack, commons)

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.js | 18.9 kB | 18.9 kB | โœ“ |
| main-HASH.js gzip | 6.79 kB | 6.79 kB | โœ“ |
| webpack-HASH.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH.js gzip | 746 B | 746 B | โœ“ |
| 4952ddcd88e7..2b8407376.js | 21.9 kB | 21.9 kB | โœ“ |
| 4952ddcd88e7..7376.js gzip | 7.81 kB | 7.81 kB | โœ“ |
| de003c3a9d30..6604acae7.js | 43.2 kB | 43.2 kB | โœ“ |
| de003c3a9d30..cae7.js gzip | 15.5 kB | 15.5 kB | โœ“ |
| framework.5b..dbaff70d3.js | 125 kB | 125 kB | โœ“ |
| framework.5b..70d3.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 211 kB | 211 kB | โœ“ |


Client Bundles (main, webpack, commons) Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.module.js | 17.2 kB | 17.2 kB | โœ“ |
| main-HASH.module.js gzip | 6.52 kB | 6.52 kB | โœ“ |
| webpack-HASH.module.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH..dule.js gzip | 746 B | 746 B | โœ“ |
| de003c3a9d30..42.module.js | 45.6 kB | 45.6 kB | โœ“ |
| de003c3a9d30..dule.js gzip | 16.5 kB | 16.5 kB | โœ“ |
| framework.5b..d3.module.js | 125 kB | 125 kB | โœ“ |
| framework.5b..dule.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 190 kB | 190 kB | โœ“ |


Client Pages

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.js | 1.81 kB | 1.81 kB | โœ“ |
| _app.js gzip | 873 B | 873 B | โœ“ |
| _error.js | 12 kB | 12 kB | โœ“ |
| _error.js gzip | 4.73 kB | 4.73 kB | โœ“ |
| hooks.js | 12.7 kB | 12.7 kB | โœ“ |
| hooks.js gzip | 4.79 kB | 4.79 kB | โœ“ |
| index.js | 318 B | 318 B | โœ“ |
| index.js gzip | 222 B | 222 B | โœ“ |
| link.js | 8.14 kB | 8.14 kB | โœ“ |
| link.js gzip | 3.5 kB | 3.5 kB | โœ“ |
| routerDirect.js | 408 B | 408 B | โœ“ |
| routerDirect.js gzip | 281 B | 281 B | โœ“ |
| withRouter.js | 419 B | 419 B | โœ“ |
| withRouter.js gzip | 280 B | 280 B | โœ“ |
| Overall change | 35.8 kB | 35.8 kB | โœ“ |


Client Pages Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.module.js | 1.7 kB | 1.7 kB | โœ“ |
| _app.module.js gzip | 832 B | 832 B | โœ“ |
| _error.module.js | 23.3 kB | 23.3 kB | โœ“ |
| _error.module.js gzip | 8.59 kB | 8.59 kB | โœ“ |
| hooks.module.js | 1.52 kB | 1.52 kB | โœ“ |
| hooks.module.js gzip | 793 B | 793 B | โœ“ |
| index.module.js | 294 B | 294 B | โœ“ |
| index.module.js gzip | 223 B | 223 B | โœ“ |
| link.module.js | 8.53 kB | 8.53 kB | โœ“ |
| link.module.js gzip | 3.68 kB | 3.68 kB | โœ“ |
| routerDirect.module.js | 394 B | 394 B | โœ“ |
| routerDirect..dule.js gzip | 281 B | 281 B | โœ“ |
| withRouter.module.js | 404 B | 404 B | โœ“ |
| withRouter.m..dule.js gzip | 278 B | 278 B | โœ“ |
| Overall change | 36.1 kB | 36.1 kB | โœ“ |


Client Build Manifests

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _buildManifest.js | 81 B | 81 B | โœ“ |
| _buildManifest.js gzip | 61 B | 61 B | โœ“ |
| _buildManifest.module.js | 81 B | 81 B | โœ“ |
| _buildManife..dule.js gzip | 61 B | 61 B | โœ“ |
| Overall change | 162 B | 162 B | โœ“ |


Rendered Page Sizes

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| index.html | 3.62 kB | 3.62 kB | โœ“ |
| index.html gzip | 947 B | 947 B | โœ“ |
| link.html | 3.66 kB | 3.66 kB | โœ“ |
| link.html gzip | 955 B | 955 B | โœ“ |
| withRouter.html | 3.67 kB | 3.67 kB | โœ“ |
| withRouter.html gzip | 942 B | 942 B | โœ“ |
| Overall change | 10.9 kB | 10.9 kB | โœ“ |





Serverless Mode



General

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| buildDuration | 17.2s | 17s | -236ms |
| nodeModulesSize | 48.3 MB | 48.3 MB | โœ“ |


Client Bundles (main, webpack, commons)

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.js | 18.9 kB | 18.9 kB | โœ“ |
| main-HASH.js gzip | 6.79 kB | 6.79 kB | โœ“ |
| webpack-HASH.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH.js gzip | 746 B | 746 B | โœ“ |
| 4952ddcd88e7..2b8407376.js | 21.9 kB | 21.9 kB | โœ“ |
| 4952ddcd88e7..7376.js gzip | 7.81 kB | 7.81 kB | โœ“ |
| de003c3a9d30..6604acae7.js | 43.2 kB | 43.2 kB | โœ“ |
| de003c3a9d30..cae7.js gzip | 15.5 kB | 15.5 kB | โœ“ |
| framework.5b..dbaff70d3.js | 125 kB | 125 kB | โœ“ |
| framework.5b..70d3.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 211 kB | 211 kB | โœ“ |


Client Bundles (main, webpack, commons) Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.module.js | 17.2 kB | 17.2 kB | โœ“ |
| main-HASH.module.js gzip | 6.52 kB | 6.52 kB | โœ“ |
| webpack-HASH.module.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH..dule.js gzip | 746 B | 746 B | โœ“ |
| de003c3a9d30..42.module.js | 45.6 kB | 45.6 kB | โœ“ |
| de003c3a9d30..dule.js gzip | 16.5 kB | 16.5 kB | โœ“ |
| framework.5b..d3.module.js | 125 kB | 125 kB | โœ“ |
| framework.5b..dule.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 190 kB | 190 kB | โœ“ |


Client Pages

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.js | 1.81 kB | 1.81 kB | โœ“ |
| _app.js gzip | 873 B | 873 B | โœ“ |
| _error.js | 12 kB | 12 kB | โœ“ |
| _error.js gzip | 4.73 kB | 4.73 kB | โœ“ |
| hooks.js | 12.7 kB | 12.7 kB | โœ“ |
| hooks.js gzip | 4.79 kB | 4.79 kB | โœ“ |
| index.js | 318 B | 318 B | โœ“ |
| index.js gzip | 222 B | 222 B | โœ“ |
| link.js | 8.14 kB | 8.14 kB | โœ“ |
| link.js gzip | 3.5 kB | 3.5 kB | โœ“ |
| routerDirect.js | 408 B | 408 B | โœ“ |
| routerDirect.js gzip | 281 B | 281 B | โœ“ |
| withRouter.js | 419 B | 419 B | โœ“ |
| withRouter.js gzip | 280 B | 280 B | โœ“ |
| Overall change | 35.8 kB | 35.8 kB | โœ“ |


Client Pages Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.module.js | 1.7 kB | 1.7 kB | โœ“ |
| _app.module.js gzip | 832 B | 832 B | โœ“ |
| _error.module.js | 23.3 kB | 23.3 kB | โœ“ |
| _error.module.js gzip | 8.59 kB | 8.59 kB | โœ“ |
| hooks.module.js | 1.52 kB | 1.52 kB | โœ“ |
| hooks.module.js gzip | 793 B | 793 B | โœ“ |
| index.module.js | 294 B | 294 B | โœ“ |
| index.module.js gzip | 223 B | 223 B | โœ“ |
| link.module.js | 8.53 kB | 8.53 kB | โœ“ |
| link.module.js gzip | 3.68 kB | 3.68 kB | โœ“ |
| routerDirect.module.js | 394 B | 394 B | โœ“ |
| routerDirect..dule.js gzip | 281 B | 281 B | โœ“ |
| withRouter.module.js | 404 B | 404 B | โœ“ |
| withRouter.m..dule.js gzip | 278 B | 278 B | โœ“ |
| Overall change | 36.1 kB | 36.1 kB | โœ“ |


Client Build Manifests

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _buildManifest.js | 81 B | 81 B | โœ“ |
| _buildManifest.js gzip | 61 B | 61 B | โœ“ |
| _buildManifest.module.js | 81 B | 81 B | โœ“ |
| _buildManife..dule.js gzip | 61 B | 61 B | โœ“ |
| Overall change | 162 B | 162 B | โœ“ |


Serverless bundles

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _error.js | 253 kB | 253 kB | โœ“ |
| _error.js gzip | 67.9 kB | 67.9 kB | โœ“ |
| hooks.html | 3.75 kB | 3.75 kB | โœ“ |
| hooks.html gzip | 979 B | 979 B | โœ“ |
| index.js | 254 kB | 254 kB | โœ“ |
| index.js gzip | 68.2 kB | 68.2 kB | โœ“ |
| link.js | 261 kB | 261 kB | โœ“ |
| link.js gzip | 70.3 kB | 70.3 kB | โœ“ |
| routerDirect.js | 255 kB | 255 kB | โœ“ |
| routerDirect.js gzip | 68.3 kB | 68.3 kB | โœ“ |
| withRouter.js | 254 kB | 254 kB | โœ“ |
| withRouter.js gzip | 68.4 kB | 68.4 kB | โœ“ |
| Overall change | 1.28 MB | 1.28 MB | โœ“ |

Commit: 3f51f0ed8010d0dcef4f2ffe1af5992d363c6456

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jesselee34 picture jesselee34  ยท  3Comments

irrigator picture irrigator  ยท  3Comments

swrdfish picture swrdfish  ยท  3Comments

wagerfield picture wagerfield  ยท  3Comments

YarivGilad picture YarivGilad  ยท  3Comments