diff --git a/src/components/interactive-map.js b/src/components/interactive-map.js index f5cba7f4..56655a81 100644 --- a/src/components/interactive-map.js +++ b/src/components/interactive-map.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import {useContext, useRef, useMemo, useEffect, useLayoutEffect, forwardRef} from 'react'; +import {useContext, useRef, useMemo, useEffect, forwardRef} from 'react'; import * as PropTypes from 'prop-types'; import StaticMap from './static-map'; @@ -11,6 +11,7 @@ import MapContext, {MapContextProvider} from './map-context'; import {EventManager} from 'mjolnir.js'; import MapController from '../utils/map-controller'; +import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect'; const propTypes = Object.assign({}, StaticMap.propTypes, { // Additional props on top of StaticMap @@ -393,7 +394,7 @@ const InteractiveMap = forwardRef((props, ref) => { }; }, []); - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (viewportUpdateRequested) { // Perform deferred updates handleViewportChange(...viewportUpdateRequested); @@ -418,7 +419,7 @@ const InteractiveMap = forwardRef((props, ref) => { [style, width, height, getCursor, thisRef.state] ); - if (!viewportUpdateRequested) { + if (!viewportUpdateRequested || !thisRef._child) { // Only rerender if no viewport update has been requested during render. // Otherwise return the last rendered child, and invoke the callback when we're done. thisRef._child = ( diff --git a/src/components/static-map.js b/src/components/static-map.js index 08871d08..d8adac5a 100644 --- a/src/components/static-map.js +++ b/src/components/static-map.js @@ -24,7 +24,6 @@ import { useEffect, useContext, useMemo, - useLayoutEffect, useImperativeHandle, forwardRef } from 'react'; @@ -38,6 +37,7 @@ import mapboxgl from '../utils/mapboxgl'; import {checkVisibilityConstraints} from '../utils/map-constraints'; import {MAPBOX_LIMITS} from '../utils/map-state'; import MapContext, {MapContextProvider} from './map-context'; +import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect'; /* eslint-disable max-len */ const TOKEN_DOC_URL = 'https://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens'; @@ -174,7 +174,7 @@ const StaticMap = forwardRef((props, ref) => { }; }, []); - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (mapboxRef.current) { mapboxRef.current.setProps( Object.assign({}, props, { diff --git a/src/utils/use-isomorphic-layout-effect.js b/src/utils/use-isomorphic-layout-effect.js new file mode 100644 index 00000000..0110143a --- /dev/null +++ b/src/utils/use-isomorphic-layout-effect.js @@ -0,0 +1,7 @@ +// From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts +// useLayoutEffect but does not trigger warning in server-side rendering +import {useEffect, useLayoutEffect} from 'react'; + +const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; + +export default useIsomorphicLayoutEffect;