mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Make next/router a client only API. (#443)
* Prevent using 'next/router' APIs inside 'getInitialProps' * Remove incorrect documentation. * Make next/router a client only API.
This commit is contained in:
parent
660147f661
commit
141c045c68
|
@ -24,8 +24,6 @@ export default () => (
|
|||
<div>
|
||||
<Link href='/'>Home</Link>
|
||||
<Link href='/about'>About</Link>
|
||||
<div>
|
||||
<small>Now you are in the route: {Router.route} </small>
|
||||
</div>
|
||||
<Link href='/error'>Error</Link>
|
||||
</div>
|
||||
)
|
||||
|
|
16
examples/using-router/pages/error.js
Normal file
16
examples/using-router/pages/error.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import React from 'react'
|
||||
import Header from '../components/Header'
|
||||
import Router from 'next/router'
|
||||
|
||||
const ErrorPage = ({ aa }) => (
|
||||
<div>
|
||||
<Header />
|
||||
<p>This should not be rendered via SSR</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
ErrorPage.getInitialProps = () => {
|
||||
console.log(Router.pathname)
|
||||
}
|
||||
|
||||
export default ErrorPage
|
|
@ -6,7 +6,7 @@ let router = null
|
|||
const SingletonRouter = {}
|
||||
|
||||
// Create public properties and methods of the router in the SingletonRouter
|
||||
const propertyFields = ['route', 'components', 'pathname', 'query']
|
||||
const propertyFields = ['components', 'pathname', 'route', 'query']
|
||||
const methodFields = ['push', 'replace', 'reload', 'back']
|
||||
|
||||
propertyFields.forEach((field) => {
|
||||
|
@ -16,6 +16,7 @@ propertyFields.forEach((field) => {
|
|||
// proper way to access it
|
||||
Object.defineProperty(SingletonRouter, field, {
|
||||
get () {
|
||||
throwIfNoRouter()
|
||||
return router[field]
|
||||
}
|
||||
})
|
||||
|
@ -23,29 +24,33 @@ propertyFields.forEach((field) => {
|
|||
|
||||
methodFields.forEach((field) => {
|
||||
SingletonRouter[field] = (...args) => {
|
||||
throwIfNoRouter()
|
||||
return router[field](...args)
|
||||
}
|
||||
})
|
||||
|
||||
// This is an internal method and it should not be called directly.
|
||||
//
|
||||
// ## Client Side Usage
|
||||
// We create the router in the client side only for a single time when we are
|
||||
// booting the app. It happens before rendering any components.
|
||||
// At the time of the component rendering, there'll be a router instance
|
||||
//
|
||||
// ## Server Side Usage
|
||||
// We create router for every SSR page render.
|
||||
// Since rendering happens in the same eventloop this works properly.
|
||||
function throwIfNoRouter () {
|
||||
if (!router) {
|
||||
const message = 'No router instance found.\n' +
|
||||
'You should only use "next/router" inside the client side of your app.\n'
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
||||
|
||||
// Export the SingletonRouter and this is the public API.
|
||||
export default SingletonRouter
|
||||
|
||||
// INTERNAL APIS
|
||||
// -------------
|
||||
// (do not use following exports inside the app)
|
||||
|
||||
// Create a router and assign it as the singleton instance.
|
||||
// This is used in client side when we are initilizing the app.
|
||||
// This should **not** use inside the server.
|
||||
export const createRouter = function (...args) {
|
||||
router = new _Router(...args)
|
||||
return router
|
||||
}
|
||||
|
||||
// Export the actual Router class, which is also use internally
|
||||
// You'll ever need to access this directly
|
||||
// Export the actual Router class, which is usually used inside the server
|
||||
export const Router = _Router
|
||||
|
||||
// Export the SingletonRouter and this is the public API.
|
||||
// This is an client side API and doesn't available on the server
|
||||
export default SingletonRouter
|
||||
|
|
|
@ -3,7 +3,7 @@ import { createElement } from 'react'
|
|||
import { renderToString, renderToStaticMarkup } from 'react-dom/server'
|
||||
import requireModule from './require'
|
||||
import read from './read'
|
||||
import { createRouter } from '../lib/router'
|
||||
import { Router } from '../lib/router'
|
||||
import Head, { defaultHead } from '../lib/head'
|
||||
import App from '../lib/app'
|
||||
|
||||
|
@ -56,12 +56,12 @@ async function doRender (req, res, pathname, query, {
|
|||
if (res.finished) return
|
||||
|
||||
const renderPage = () => {
|
||||
const router = createRouter(pathname, query)
|
||||
const app = createElement(App, {
|
||||
Component,
|
||||
props,
|
||||
router
|
||||
router: new Router(pathname, query)
|
||||
})
|
||||
|
||||
const html = (staticMarkup ? renderToStaticMarkup : renderToString)(app)
|
||||
const head = Head.rewind() || defaultHead()
|
||||
return { html, head }
|
||||
|
|
Loading…
Reference in a new issue