mirror of
https://github.com/visgl/react-map-gl.git
synced 2026-01-25 16:02:50 +00:00
Fix Popup and GeolocateControl under React StrictMode (#1836)
This commit is contained in:
parent
192749794d
commit
40da7db47c
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
@ -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')
|
||||
}
|
||||
},
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user