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:
parent
d3f8de3306
commit
0dd2b2aa74
14
errors/popstate-state-empty.md
Normal file
14
errors/popstate-state-empty.md
Normal 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)
|
|
@ -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`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -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', {
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue