From 8a369bfe9e74907b0ad9b23bb1f3eef87b90d83f Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 9 Aug 2019 21:18:08 -0400 Subject: [PATCH 1/6] Disable onChange and route() during SSR When rendered via `preact-render-to-string`, `onChange` and `route()` both don't make sense - updates can't be rendered since rendering is synchronous and single-pass, so we'll just disable this functionality entirely. --- src/index.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index a34bd2d3..acb67ee8 100644 --- a/src/index.js +++ b/src/index.js @@ -151,7 +151,7 @@ class Router extends Component { this.state = { url: props.url || getCurrentUrl() }; - + initEventListeners(); } @@ -179,7 +179,12 @@ class Router extends Component { } componentWillMount() { - ROUTERS.push(this); + // preact-render-to-string initializes components with the dirty flag set. + // We can use this to detect a static rendering environment and disable subscriptions. + this._ssr = this.__d || this._dirty; + if (!this._ssr) { + ROUTERS.push(this); + } this.updating = true; } @@ -194,7 +199,7 @@ class Router extends Component { componentWillUnmount() { if (typeof this.unlisten==='function') this.unlisten(); - ROUTERS.splice(ROUTERS.indexOf(this), 1); + ROUTERS.splice(ROUTERS.indexOf(this) >>> 0, 1); } componentWillUpdate() { @@ -231,7 +236,7 @@ class Router extends Component { this._didRoute = !!current; let previous = this.previousUrl; - if (url!==previous) { + if (!this._ssr && url!==previous) { this.previousUrl = url; if (typeof onChange==='function') { onChange({ From 647ec985e86140d0714a90def8e5e13016536351 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 21 Oct 2019 10:41:31 -0400 Subject: [PATCH 2/6] Adopt Preact X -compatible version --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 61b080c4..7cc33aa2 100644 --- a/src/index.js +++ b/src/index.js @@ -181,7 +181,7 @@ class Router extends Component { componentWillMount() { // preact-render-to-string initializes components with the dirty flag set. // We can use this to detect a static rendering environment and disable subscriptions. - this._ssr = this.__d || this._dirty; + this._ssr = '_nextState' in this || '__s' in this; if (!this._ssr) { ROUTERS.push(this); } From ce3002eefb580193e1e7739c9c70126a00844375 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 21 Oct 2019 10:42:04 -0400 Subject: [PATCH 3/6] update comment --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 7cc33aa2..ac22eac7 100644 --- a/src/index.js +++ b/src/index.js @@ -179,7 +179,7 @@ class Router extends Component { } componentWillMount() { - // preact-render-to-string initializes components with the dirty flag set. + // preact-render-to-string does not initialize the "next state" field for components. // We can use this to detect a static rendering environment and disable subscriptions. this._ssr = '_nextState' in this || '__s' in this; if (!this._ssr) { From 373eceec9907c0401fee4b174cb62def6391295d Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 21 Oct 2019 10:49:28 -0400 Subject: [PATCH 4/6] Fix inverted SSR condition. --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index ac22eac7..9128f06c 100644 --- a/src/index.js +++ b/src/index.js @@ -181,7 +181,7 @@ class Router extends Component { componentWillMount() { // preact-render-to-string does not initialize the "next state" field for components. // We can use this to detect a static rendering environment and disable subscriptions. - this._ssr = '_nextState' in this || '__s' in this; + this._ssr = !('_nextState' in this || '__s' in this); if (!this._ssr) { ROUTERS.push(this); } From 3f498b4e69a4b6a565ded739ead78dc970e0c974 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 21 Oct 2019 11:20:49 -0400 Subject: [PATCH 5/6] Update tests to simulate client-side rendering --- test/index.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/test/index.js b/test/index.js index a63492be..3776be4b 100644 --- a/test/index.js +++ b/test/index.js @@ -4,6 +4,12 @@ import assertCloneOf from '../test_helpers/assert-clone-of'; chai.use(assertCloneOf); +function createBrowserRouter(props) { + const router = new Router(props); + router.__s = router.state || {}; // _nextState + router.componentWillMount(); +} + describe('preact-router', () => { it('should export Router, Link and route', () => { expect(Router).to.be.a('function'); @@ -13,7 +19,7 @@ describe('preact-router', () => { describe('Router', () => { it('should filter children based on URL', () => { - let router = new Router({}); + let router = createBrowserRouter({}); let children = [ , , @@ -34,7 +40,7 @@ describe('preact-router', () => { }); it('should support nested parameterized routes', () => { - let router = new Router({}); + let router = createBrowserRouter({}); let children = [ , , @@ -55,7 +61,7 @@ describe('preact-router', () => { }); it('should support default routes', () => { - let router = new Router({}); + let router = createBrowserRouter({}); let children = [ , , @@ -76,7 +82,7 @@ describe('preact-router', () => { }); it('should support initial route prop', () => { - let router = new Router({ url:'/foo' }); + let router = createBrowserRouter({ url:'/foo' }); let children = [ , , @@ -87,14 +93,14 @@ describe('preact-router', () => { router.render({ children }, router.state) ).to.be.cloneOf(children[2]); - expect(new Router({})).to.have.deep.property('state.url', location.pathname + (location.search || '')); + expect(createBrowserRouter({})).to.have.deep.property('state.url', location.pathname + (location.search || '')); }); it('should support custom history', () => { let push = sinon.spy(); let replace = sinon.spy(); let getCurrentLocation = sinon.spy(() => ({pathname: '/initial'})); - let router = new Router({ + let router = createBrowserRouter({ history: { push, replace, getCurrentLocation }, children: [ , @@ -123,7 +129,7 @@ describe('preact-router', () => { let router; before( () => { - router = new Router({ + router = createBrowserRouter({ url: '/foo', children: [ , From dcb3afacc3f9aadbf098666157b3b6b8406b1f3c Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 21 Oct 2019 13:36:43 -0400 Subject: [PATCH 6/6] Update index.js --- test/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/index.js b/test/index.js index 3776be4b..319ccb71 100644 --- a/test/index.js +++ b/test/index.js @@ -7,7 +7,9 @@ chai.use(assertCloneOf); function createBrowserRouter(props) { const router = new Router(props); router.__s = router.state || {}; // _nextState + router.__d = true; // _dirty router.componentWillMount(); + return router; } describe('preact-router', () => {