From 988bddddfd8fd53c8d77873a1f7aa7e77e4731ae Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Fri, 28 Sep 2018 11:34:50 +0300 Subject: [PATCH] lazyLoadWithDimensions: option to load component after user has scrolled the page --- src/util/contextHelpers.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/util/contextHelpers.js b/src/util/contextHelpers.js index 713d030c..a72b0da6 100644 --- a/src/util/contextHelpers.js +++ b/src/util/contextHelpers.js @@ -75,7 +75,9 @@ export const withViewport = Component => { * the shape `{ width: 600, height: 400}`. * * @param {React.Component} Component to be wrapped by this HOC - * @param {Object} options pass in options like maxWidth and maxHeight. + * @param {Object} options pass in options like maxWidth and maxHeight. To load component after + * initial rendering has passed or after user has interacted with the window (e.g. scrolled), + * use`loadAfterInitialRendering: 1500` (value should be milliseconds). * * @return {Object} HOC component which knows its dimensions */ @@ -96,6 +98,7 @@ export const lazyLoadWithDimensions = (Component, options = {}) => { super(props); this.element = null; this.defaultRenderTimeout = null; + this.afterRenderTimeout = null; this.state = { width: 0, height: 0 }; @@ -112,6 +115,15 @@ export const lazyLoadWithDimensions = (Component, options = {}) => { this.defaultRenderTimeout = window.setTimeout(() => { if (this.isElementNearViewport(0)) { this.setDimensions(); + } else { + const loadAfterInitialRendering = options.loadAfterInitialRendering; + if (typeof loadAfterInitialRendering === 'number') { + this.afterRenderTimeout = window.setTimeout(() => { + window.requestAnimationFrame(() => { + this.setDimensions(); + }); + }, loadAfterInitialRendering); + } } }, RENDER_WAIT_MS); } @@ -121,11 +133,18 @@ export const lazyLoadWithDimensions = (Component, options = {}) => { window.removeEventListener('resize', this.handleWindowResize); window.removeEventListener('orientationchange', this.handleWindowResize); window.clearTimeout(this.defaultRenderTimeout); + + if (this.afterRenderTimeout) { + window.clearTimeout(this.afterRenderTimeout); + } } handleWindowResize() { - if (this.isElementNearViewport(NEAR_VIEWPORT_MARGIN)) { - this.setDimensions(); + const shouldLoadToImproveScrolling = typeof options.loadAfterInitialRendering === 'number'; + if (this.isElementNearViewport(NEAR_VIEWPORT_MARGIN) || shouldLoadToImproveScrolling) { + window.requestAnimationFrame(() => { + this.setDimensions(); + }); } }