Fix Popup and GeolocateControl under React StrictMode (#1836)

This commit is contained in:
Xiaoji Chen 2022-04-21 11:57:42 -07:00 committed by Xiaoji Chen
parent 192749794d
commit 40da7db47c
8 changed files with 37 additions and 16 deletions

View File

@ -91,11 +91,11 @@ CSS style override that applies to the popup's container.
#### `onOpen`: (evt: [PopupEvent](/docs/api-reference/types.md#popupevent)) => void
Called when the popup is opened manually or programatically.
Called when the popup is opened.
#### `onClose`: (evt: [PopupEvent](/docs/api-reference/types.md#popupevent)) => void
Called when the popup is closed manually or programatically.
Called when the popup is closed by the user clicking on the close button or outside (if `closeOnClick: true`).
## Source

View File

@ -28,8 +28,14 @@ export default function App() {
longitude={city.longitude}
latitude={city.latitude}
anchor="bottom"
onClick={e => {
// If we let the click event propagates to the map, it will immediately close the popup
// with `closeOnClick: true`
e.originalEvent.stopPropagation();
setPopupInfo(city);
}}
>
<Pin onClick={() => setPopupInfo(city)} />
<Pin />
</Marker>
)),
[]
@ -60,7 +66,6 @@ export default function App() {
anchor="top"
longitude={Number(popupInfo.longitude)}
latitude={Number(popupInfo.latitude)}
closeOnClick={false}
onClose={() => setPopupInfo(null)}
>
<div>

View File

@ -10,9 +10,9 @@ const pinStyle = {
stroke: 'none'
};
function Pin({size = 20, onClick}: {size?: number; onClick?: () => void}) {
function Pin({size = 20}) {
return (
<svg height={size} viewBox="0 0 24 24" style={pinStyle} onClick={onClick}>
<svg height={size} viewBox="0 0 24 24" style={pinStyle}>
<path d={ICON} />
</svg>
);

View File

@ -28,7 +28,7 @@ const LOCAL_DEVELOPMENT_CONFIG = {
alias: {
// Imports the react-map-gl library from the src directory in this repo
'react-map-gl': SRC_DIR,
'../utils/mapboxgl': resolve(LIB_DIR, './node_modules/mapbox-gl/dist/mapbox-gl-dev.js'),
'mapbox-gl': resolve(LIB_DIR, './node_modules/mapbox-gl/dist/mapbox-gl-dev.js'),
react: resolve(LIB_DIR, './node_modules/react')
}
},

View File

@ -53,7 +53,7 @@
"babel-loader": "^8.0.0",
"coveralls": "^3.0.0",
"jsdom": "^15.0.0",
"mapbox-gl": "^2.1.0",
"mapbox-gl": "^2.8.0",
"ocular-dev-tools": "beta",
"pre-commit": "^1.2.2",
"react": "^17.0.0",

View File

@ -74,6 +74,16 @@ const GeolocateControl = forwardRef<GeolocateControlRef, GeolocateControlProps>(
({mapLib}) => {
const gc = new mapLib.GeolocateControl(props);
// Hack: fix GeolocateControl reuse
// When using React strict mode, the component is mounted twice.
// GeolocateControl's UI creation is asynchronous. Removing and adding it back causes the UI to be initialized twice.
const setupUI = gc._setupUI;
gc._setupUI = args => {
if (!gc._container.hasChildNodes()) {
setupUI(args);
}
};
gc.on('geolocate', e => {
thisRef.current.props.onGeolocate?.(e as GeolocateResultEvent);
});

View File

@ -81,19 +81,25 @@ function Popup(props: PopupProps) {
const popup: MapboxPopup = useMemo(() => {
const options = {...props};
const pp = new mapLib.Popup(options).setLngLat([props.longitude, props.latitude]);
pp.on('open', e => {
pp.once('open', e => {
thisRef.current.props.onOpen?.(e as PopupEvent);
});
pp.on('close', e => {
thisRef.current.props.onClose?.(e as PopupEvent);
});
return pp;
}, []);
useEffect(() => {
const onClose = e => {
thisRef.current.props.onClose?.(e as PopupEvent);
};
popup.on('close', onClose);
popup.setDOMContent(container).addTo(map.getMap());
return () => {
// https://github.com/visgl/react-map-gl/issues/1825
// onClose should not be fired if the popup is removed by unmounting
// When using React strict mode, the component is mounted twice.
// Firing the onClose callback here would be a false signal to remove the component.
popup.off('close', onClose);
if (popup.isOpen()) {
popup.remove();
}

View File

@ -7291,10 +7291,10 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
mapbox-gl@^2.1.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-2.6.1.tgz#de8aadeb16b157b732d174b51aeaba0223ab71bb"
integrity sha512-faGbSZfcFuZ4GWwkWnJrRD3oICZAt/mVKnGuOmeBobCj9onfTRz270qSoOXeRBKd3po5VA2cCPI91YwA8DsAoQ==
mapbox-gl@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-2.8.0.tgz#698f028575f202d25f2ccb5d6359761d1affb8e2"
integrity sha512-sP7TclFDmGhZWfcBlptnA24xO9T4a419W2Y6znGvuRXLkucnGErDIG+/7WLVDrebMYp4E2FtCG+1RtGcYVRIFQ==
dependencies:
"@mapbox/geojson-rewind" "^0.5.1"
"@mapbox/geojson-types" "^1.0.2"