Open dispatchr1 opened 3 years ago
@dispatchr1 did you solve it ?
Also having this issue.
Just like we add children to our container with the addTo
method, we can remove them using the Node.removeChild API. This would live in the cleanup callback of our useEffect hook.
useEffect(() => {
geocoder.addTo("#geocoder");
return () => {
const parentContainer = document.getElementById("geocoder");
const geoChild = document.getElementsByClassName(
"mapboxgl-ctrl-geocoder"
);
if (!parentContainer || !geoChild) return;
parentContainer.removeChild(geoChild[0]);
};
}, []);
If you are weary about a change in className
breaking your implementation. Then you can loosen the coupling by removing all children on every cleanup. Below I should only the cleanup callback.
return () => {
const element = document.getElementById("geocoder");
if (!element) return;
while (element.firstChild) {
element.removeChild(element.firstChild);
}
};
This is how I solved.
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
import mapboxgl from 'mapbox-gl';
import { useEffect, useRef, useState } from 'react';
mapboxgl.accessToken = import.meta.env.APP_MAPBOX_PUBLIC_TOKEN;
const geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
types: 'country,region,place,postcode,locality,neighborhood'
});
interface PlaceAutocompleteProps {
}
export default function PlaceAutocomplete(_props: PlaceAutocompleteProps) {
const autocompleteRef = useRef<HTMLDivElement>(null);
const [result, setResult] = useState<any>(null);
useEffect(() => {
const onResult = (e: any) => {
setResult(e.result);
}
const onClear = () => {
setResult(null);
}
geocoder.addTo(autocompleteRef.current);
geocoder.on('result', onResult);
geocoder.on('clear', onClear);
return () => {
geocoder.off('result', onResult);
geocoder.off('result', onClear);
if(autocompleteRef.current) {
autocompleteRef.current.innerHTML = ''; // <-------------- This line does the trick
}
}
}, []);
return (<>
<div className='w-full' ref={autocompleteRef}></div>
<pre>{JSON.stringify(result, null, 2)}</pre>
</>)
}
System Info
OS macOS 10.13.6 High Sierra Node version 14.15 Libraries:
Symptoms
I'm using the geocoder js library in a react application and seeing that the input is rendered each time my development server restarts (create react app fast refresh). I believe the appropriate enhancement is to provide a clean up function to remove the geocoder on component unmount, similar to the
map.remove()
function provided bymapboxgl.Map()
as per the react example repoCode sample
Screenshot