From bd85a56e48cf526557d44dac3e2049b992d5672e Mon Sep 17 00:00:00 2001 From: Xiaoji Chen Date: Mon, 11 Feb 2019 13:33:43 -0800 Subject: [PATCH] Force map rerender synchronously after props update (#720) --- src/mapbox/mapbox.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/mapbox/mapbox.js b/src/mapbox/mapbox.js index 1ce8650ac..05246c149 100644 --- a/src/mapbox/mapbox.js +++ b/src/mapbox/mapbox.js @@ -211,11 +211,23 @@ export default class Mapbox { // (e.g. until "componentDidUpdate") resize() { this._map.resize(); + return this; + } + + // Force redraw the map now. Typically resize() and jumpTo() is reflected in the next + // render cycle, which is managed by Mapbox's animation loop. + // This removes the synchronization issue caused by requestAnimationFrame. + redraw() { + const map = this._map; // map render will throw error if style is not loaded - if (this._map.isStyleLoaded()) { - this._map._render(); + if (map.isStyleLoaded()) { + map._render(); + // cancel the scheduled update + if (map._frame) { + map._frame.cancel(); + map._frame = null; + } } - return this; } // External apps can access map this way @@ -369,8 +381,12 @@ export default class Mapbox { newProps = Object.assign({}, this.props, newProps); checkPropTypes(newProps, 'Mapbox'); - this._updateMapViewport(oldProps, newProps); - this._updateMapSize(oldProps, newProps); + const viewportChanged = this._updateMapViewport(oldProps, newProps); + const sizeChanged = this._updateMapSize(oldProps, newProps); + + if (viewportChanged || sizeChanged) { + this.redraw(); + } this.props = newProps; } @@ -383,6 +399,7 @@ export default class Mapbox { this.height = newProps.height; this.resize(); } + return sizeChanged; } _updateMapViewport(oldProps: any, newProps: Props) { @@ -405,6 +422,7 @@ export default class Mapbox { this._map.transform.altitude = newViewState.altitude; } } + return viewportChanged; } _getViewState(props: Props) : ViewState {