From 0aac59464d3f932d6b259abd5879a12ddd71d38b Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 9 Oct 2019 13:32:19 -0500 Subject: [PATCH 1/3] Update to use a historyId to track invalid popstates --- .../next/next-server/lib/router/router.ts | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index 7735dd9de2f42..3024374889f01 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -71,6 +71,7 @@ export default class Router implements BaseRouter { _bps: BeforePopStateCallback | undefined events: MittEmitter _wrapApp: (App: ComponentType) => any + historyId: number static events: MittEmitter = mitt() @@ -126,6 +127,8 @@ export default class Router implements BaseRouter { this.sub = subscription this.clc = null this._wrapApp = wrapApp + // we use a historyId to enable ignoring invalid popstates + this.historyId = new Date().getTime() if (typeof window !== 'undefined') { // in order for `e.state` to work on the `onpopstate` event @@ -137,17 +140,6 @@ export default class Router implements BaseRouter { ) window.addEventListener('popstate', this.onPopState) - window.addEventListener('unload', () => { - // Workaround for popstate firing on initial page load when - // navigating back from an external site - if (history.state) { - const { url, as, options }: any = history.state - this.changeState('replaceState', url, as, { - ...options, - fromExternal: true, - }) - } - }) } } @@ -176,9 +168,11 @@ export default class Router implements BaseRouter { return } + console.log(e.state.options.historyId, this.historyId) + // Make sure we don't re-render on initial load, // can be caused by navigating back from an external site - if (e.state.options && e.state.options.fromExternal) { + if (e.state.options && e.state.options.historyId !== this.historyId) { return } @@ -379,7 +373,18 @@ export default class Router implements BaseRouter { if (method !== 'pushState' || getURL() !== as) { // @ts-ignore method should always exist on history - window.history[method]({ url, as, options }, null, as) + window.history[method]( + { + url, + as, + options: { + ...options, + historyId: this.historyId, + }, + }, + null, + as + ) } } From 005eb67ab1ad80a7eb346a47b0c3f9cb9ac1ace0 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 10 Oct 2019 05:48:36 -0500 Subject: [PATCH 2/3] Remove log from debugging --- packages/next/next-server/lib/router/router.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index 3024374889f01..d7d4e99bbc9ed 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -168,8 +168,6 @@ export default class Router implements BaseRouter { return } - console.log(e.state.options.historyId, this.historyId) - // Make sure we don't re-render on initial load, // can be caused by navigating back from an external site if (e.state.options && e.state.options.historyId !== this.historyId) { From aec294ec846ba29a6b4e7ef897f3df7e1ea5cbac Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 10 Oct 2019 09:29:49 -0500 Subject: [PATCH 3/3] Use Math.random instead of Date.getTime to avoid mocks --- packages/next/next-server/lib/router/router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index d7d4e99bbc9ed..8339ea21b8d79 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -128,7 +128,7 @@ export default class Router implements BaseRouter { this.clc = null this._wrapApp = wrapApp // we use a historyId to enable ignoring invalid popstates - this.historyId = new Date().getTime() + this.historyId = Math.random() if (typeof window !== 'undefined') { // in order for `e.state` to work on the `onpopstate` event