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>
|
<div>
|
||||||
<Link href='/'>Home</Link>
|
<Link href='/'>Home</Link>
|
||||||
<Link href='/about'>About</Link>
|
<Link href='/about'>About</Link>
|
||||||
<div>
|
<Link href='/error'>Error</Link>
|
||||||
<small>Now you are in the route: {Router.route} </small>
|
|
||||||
</div>
|
|
||||||
</div>
|
</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 = {}
|
const SingletonRouter = {}
|
||||||
|
|
||||||
// Create public properties and methods of the router in the 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']
|
const methodFields = ['push', 'replace', 'reload', 'back']
|
||||||
|
|
||||||
propertyFields.forEach((field) => {
|
propertyFields.forEach((field) => {
|
||||||
|
@ -16,6 +16,7 @@ propertyFields.forEach((field) => {
|
||||||
// proper way to access it
|
// proper way to access it
|
||||||
Object.defineProperty(SingletonRouter, field, {
|
Object.defineProperty(SingletonRouter, field, {
|
||||||
get () {
|
get () {
|
||||||
|
throwIfNoRouter()
|
||||||
return router[field]
|
return router[field]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -23,29 +24,33 @@ propertyFields.forEach((field) => {
|
||||||
|
|
||||||
methodFields.forEach((field) => {
|
methodFields.forEach((field) => {
|
||||||
SingletonRouter[field] = (...args) => {
|
SingletonRouter[field] = (...args) => {
|
||||||
|
throwIfNoRouter()
|
||||||
return router[field](...args)
|
return router[field](...args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// This is an internal method and it should not be called directly.
|
function throwIfNoRouter () {
|
||||||
//
|
if (!router) {
|
||||||
// ## Client Side Usage
|
const message = 'No router instance found.\n' +
|
||||||
// We create the router in the client side only for a single time when we are
|
'You should only use "next/router" inside the client side of your app.\n'
|
||||||
// booting the app. It happens before rendering any components.
|
throw new Error(message)
|
||||||
// At the time of the component rendering, there'll be a router instance
|
}
|
||||||
//
|
}
|
||||||
// ## Server Side Usage
|
|
||||||
// We create router for every SSR page render.
|
// Export the SingletonRouter and this is the public API.
|
||||||
// Since rendering happens in the same eventloop this works properly.
|
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) {
|
export const createRouter = function (...args) {
|
||||||
router = new _Router(...args)
|
router = new _Router(...args)
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export the actual Router class, which is also use internally
|
// Export the actual Router class, which is usually used inside the server
|
||||||
// You'll ever need to access this directly
|
|
||||||
export const Router = _Router
|
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 { renderToString, renderToStaticMarkup } from 'react-dom/server'
|
||||||
import requireModule from './require'
|
import requireModule from './require'
|
||||||
import read from './read'
|
import read from './read'
|
||||||
import { createRouter } from '../lib/router'
|
import { Router } from '../lib/router'
|
||||||
import Head, { defaultHead } from '../lib/head'
|
import Head, { defaultHead } from '../lib/head'
|
||||||
import App from '../lib/app'
|
import App from '../lib/app'
|
||||||
|
|
||||||
|
@ -56,12 +56,12 @@ async function doRender (req, res, pathname, query, {
|
||||||
if (res.finished) return
|
if (res.finished) return
|
||||||
|
|
||||||
const renderPage = () => {
|
const renderPage = () => {
|
||||||
const router = createRouter(pathname, query)
|
|
||||||
const app = createElement(App, {
|
const app = createElement(App, {
|
||||||
Component,
|
Component,
|
||||||
props,
|
props,
|
||||||
router
|
router: new Router(pathname, query)
|
||||||
})
|
})
|
||||||
|
|
||||||
const html = (staticMarkup ? renderToStaticMarkup : renderToString)(app)
|
const html = (staticMarkup ? renderToStaticMarkup : renderToString)(app)
|
||||||
const head = Head.rewind() || defaultHead()
|
const head = Head.rewind() || defaultHead()
|
||||||
return { html, head }
|
return { html, head }
|
||||||
|
|
Loading…
Reference in a new issue