1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Add warning for broken popstate (#5000)

* Add warning for undefined url and as coming from popstate

* Use consistent url

* Fix err.sh link in test

* Rename `inital` => `initial`
This commit is contained in:
Tim Neutkens 2018-08-24 12:30:27 +02:00 committed by GitHub
parent d3f8de3306
commit 0dd2b2aa74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 24 additions and 5 deletions

View file

@ -0,0 +1,14 @@
# `popstate` called with empty state
#### Why This Error Occurred
When using the browser back button the popstate event is triggered. Next.js sets
`popstate` event triggered but `event.state` did not have `url` or `as`, causing a route change failure
#### Possible Ways to Fix It
The only known cause of this issue is manually manipulating `window.history` instead of using `next/router`
### Useful Links
- [The issue this was reported in: #4994](https://github.com/zeit/next.js/issues/4994)

View file

@ -79,7 +79,7 @@ export class Container extends Component {
const warnUrl = execOnce(() => { const warnUrl = execOnce(() => {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
warn(`Warning: the 'url' property is deprecated. https://err.sh/next.js/url-deprecated`) warn(`Warning: the 'url' property is deprecated. https://err.sh/zeit/next.js/url-deprecated`)
} }
}) })

View file

@ -63,7 +63,7 @@ routerEvents.forEach((event) => {
}) })
const warnAboutRouterOnAppUpdated = execOnce(() => { const warnAboutRouterOnAppUpdated = execOnce(() => {
console.warn(`Router.onAppUpdated is removed - visit https://err.sh/next.js/no-on-app-updated-hook for more information.`) console.warn(`Router.onAppUpdated is removed - visit https://err.sh/zeit/next.js/no-on-app-updated-hook for more information.`)
}) })
Object.defineProperty(SingletonRouter, 'onAppUpdated', { Object.defineProperty(SingletonRouter, 'onAppUpdated', {

View file

@ -78,6 +78,11 @@ export default class Router {
} }
const { url, as, options } = e.state const { url, as, options } = e.state
if (process.env.NODE_ENV === 'development') {
if (typeof url === 'undefined' || typeof as === 'undefined') {
console.warn('`popstate` event triggered but `event.state` did not have `url` or `as` https://err.sh/zeit/next.js/popstate-state-empty')
}
}
this.replace(url, as, options) this.replace(url, as, options)
}; };
@ -169,7 +174,7 @@ export default class Router {
const { pathname, query } = parse(url, true) const { pathname, query } = parse(url, true)
// If asked to change the current URL we should reload the current page // If asked to change the current URL we should reload the current page
// (not location.reload() but reload getInitalProps and other Next.js stuffs) // (not location.reload() but reload getInitialProps and other Next.js stuffs)
// We also need to set the method = replaceState always // We also need to set the method = replaceState always
// as this should not go into the history (That's how browsers work) // as this should not go into the history (That's how browsers work)
if (!this.urlIsNew(pathname, query)) { if (!this.urlIsNew(pathname, query)) {

View file

@ -61,7 +61,7 @@ export async function loadGetInitialProps (Component, ctx) {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
if (Component.prototype && Component.prototype.getInitialProps) { if (Component.prototype && Component.prototype.getInitialProps) {
const compName = getDisplayName(Component) const compName = getDisplayName(Component)
const message = `"${compName}.getInitialProps()" is defined as an instance method - visit https://err.sh/next.js/get-inital-props-as-an-instance-method for more information.` const message = `"${compName}.getInitialProps()" is defined as an instance method - visit https://err.sh/zeit/next.js/get-initial-props-as-an-instance-method for more information.`
throw new Error(message) throw new Error(message)
} }
} }

View file

@ -7,7 +7,7 @@ describe('loadGetInitialProps', () => {
getInitialProps () {} getInitialProps () {}
} }
const rejectPromise = loadGetInitialProps(TestComponent, {}) const rejectPromise = loadGetInitialProps(TestComponent, {})
const error = new Error('"TestComponent.getInitialProps()" is defined as an instance method - visit https://err.sh/next.js/get-inital-props-as-an-instance-method for more information.') const error = new Error('"TestComponent.getInitialProps()" is defined as an instance method - visit https://err.sh/zeit/next.js/get-inital-props-as-an-instance-method for more information.')
return expect(rejectPromise).rejects.toEqual(error) return expect(rejectPromise).rejects.toEqual(error)
}) })