Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent event bubbling on child of React-Leaflet Map

I have a React-Leaflet map which I am rendering a div inside.

For some reason, interacting with the contents of the div causes the map beneath to respond (eg: double-clicking will zoom the map, dragging will pan the map) - even when I'm calling e.stopPropagation() in handlers attached to the div.

As I understand it, calling stopPropagation() should prevent the DOM events from ever reaching the map itself.

Why does it appear that stopPropagation() is being ignored?

How can I render a div inside the map without it's events bubbling to the map itself?

Here is an example codepen showing the problem.

import { Map, TileLayer } from 'react-leaflet';

const MyMap = props => (
  <Map zoom={13} center={[51.505, -0.09]}>
    <TileLayer url={"http://{s}.tile.osm.org/{z}/{x}/{y}.png"} />

    {/* 
          HOW do I get this div to NOT pass it's events down to the map?!?! 
          Why does e.stopPropagation() appear to not work?
    */}
    <div 
      id="zone"
      onClick={e => e.stopPropagation()}
      onMouseDown={e => e.stopPropagation()}
      onMouseUp={e => e.stopPropagation()}
    >
      <p>Double-click or click and drag inside this square</p>
      <p>Why does the map zoom/pan?</p>
    </div>

  </Map>
);

ReactDOM.render(<MyMap />, document.getElementById('root'));
like image 305
Alex McMillan Avatar asked Jul 12 '19 01:07

Alex McMillan


People also ask

How do I stop event bubbling in react?

React: stopPropagation We extended one of the previous examples by using the stopPropagation() method on an event. This way, when the button gets clicked, the event does not bubble up and does not trigger the event handler of the surrounding container element.

How do you stop event capturing?

To stop an event from further propagation in the capturing and bubbling phases, you call the Event. stopPropation() method in the event handler. Note that the event. stopPropagation() method doesn't stop any default behaviors of the element e.g., link click, checkbox checked.

Is react leaflet good?

Leaflet and its React counterpart, React Leaflet, are a fantastic open source and free mapping alternative to Google Maps and MapBox, no API key required! It is an easy package to work with and one worth trying out.

What is event bubbling and event looping?

Event bubbling is a method of event propagation in the HTML DOM API when an event is in an element inside another element, and both elements have registered a handle to that event. It is a process that starts with the element that triggered the event and then bubbles up to the containing elements in the hierarchy.


1 Answers

For Leaflet map use L.DomEvent.disableClickPropagation instead which:

Adds stopPropagation to the element's 'click', 'doubleclick', 'mousedown' and 'touchstart' events.

Example

function MyMap() {
  return (
    <div>
      <Map zoom={13} center={[51.505, -0.09]}>
        <TileLayer url={"http://{s}.tile.osm.org/{z}/{x}/{y}.png"} />
        <MyInfo />
      </Map>
    </div>
  );
}

where

function MyInfo() {
  const divRef = useRef(null);

  useEffect(() => {
    L.DomEvent.disableClickPropagation(divRef.current);
  });

  return (
    <div ref={divRef} id="zone">
      <p>Double-click or click and drag inside this square</p>
      <p>Why does the map zoom/pan?</p>
    </div>
  );
}

Updated codepen

Alternative option

Another option to stop div element from propagation to map events would be to place div outside of the map element:

<div>
  <Map zoom={13} center={[51.505, -0.09]}>
    <TileLayer url={"http://{s}.tile.osm.org/{z}/{x}/{y}.png"} />
  </Map>
  <MyInfo />
</div>

where

function MyInfo() {
  return (
    <div id="zone">
      <p>Double-click or click and drag inside this square</p>
      <p>Why does the map zoom/pan?</p>
    </div>
  );
}
like image 97
Vadim Gremyachev Avatar answered Oct 16 '22 17:10

Vadim Gremyachev