0

I have been working on a map application using TomTomMap and I need to render a custom Marker component on the Map, where I can attach different Reacts events and update React state variables. In the example below this is done using the ReactDOM.render method, which is depreciated in Reactjs 18. The map and the Markers are actual DOM nodes and I always end up with DOM events on the markers when I try something different. How can you achieve the same in React 18 without using ReactDOM.Render. I'm a little need to React and sort of desperate here.

const Marker = ({ onClick, children, feature }) => {
  const _onClick = () => {
    onClick(feature.properties.description);
  };

  return (
    <button onClick={_onClick} className="marker">
      {children}
    </button>
  );
};

const Map = () => {
  const mapContainerRef = useRef(null);

  // Initialize map when component mounts
  useEffect(() => {
    const map = new mapboxgl.Map({
      container: mapContainerRef.current,
      style: "mapbox://styles/mapbox/streets-v11",
      center: [-87.65, 41.84],
      zoom: 10,
    });

    // Render custom marker components
    geoJson.features.forEach((feature) => {
      // Create a React ref
      const ref = React.createRef();
      // Create a new DOM node and save it to the React ref
      ref.current = document.createElement("div");
      // Render a Marker Component on our new DOM node
      ReactDOM.render(
        <Marker onClick={markerClicked} feature={feature} />,
        ref.current
      );

      // Create a Mapbox Marker at our new DOM node
      new mapboxgl.Marker(ref.current)
        .setLngLat(feature.geometry.coordinates)
        .addTo(map);
    });

    // Add navigation control (the +/- zoom buttons)
    map.addControl(new mapboxgl.NavigationControl(), "top-right");

    // Clean up on unmount
    return () => map.remove();
  }, []);

  const markerClicked = (title) => {
    window.alert(title);
  };

  return <div className="map-container" ref={mapContainerRef} />;
};

export default Map;

I want to attach React events to the marker components, so they can update React state variable.

1 Answers1

0

I'm not sure if I've understood the problem you are having exactly, but I am using a similar piece of code myself to render my custom markers on a map. I have moved away from the ReactDOM.render method and am using root.render instead.

I adapted the sample code from the mapbox examples github, which looks to be pretty much the same as yours, so lets see if this helps you too:

Import the following:

import { createRoot } from 'react-dom/client'

Replace the ReactDOM.render call with createRoot:

  createRoot(ref.current).render(
    <Marker onClick={markerClicked} feature={feature} />
  )

I have added a custom background image in my CSS for the className "marker" and I now have my custom markers rendering on my map with no warnings in the console.

Hope this helps!