8

Recently, I have been integrating Material Design Lite into my React web application. For the most part, everything has worked out just fine, but currently I am having some issues with React's event handling, which doesn't seem to play nice with some MDL components.

In particular, I have a DOM element with an onClick handler, which works perfectly fine, until a MDL Tooltip is added, which causes the onClick to no longer fire. I've tried pretty much every variation possible (put the tooltip somewhere else in the DOM, attach the onClick handler to a container div which has the tooltip as a child, etc), and I just can't seem to get it to work.

Here's a JSBin that demonstrates the issue (I've also included an example that uses jQuery to bind a click handler to the element after the component mounts, which actually DOES work):

http://jsbin.com/sewimi/3/edit?js,output

I have some theories as to why this isn't working, but I don't know enough about either React or MDL to verify any of them.

I believe it has something to do with the way React handles events, and for some reason, MDL seems to be clashing with it. From the documentation:

React doesn't actually attach event handlers to the nodes themselves. When React starts up, it starts listening for all events at the top level using a single event listener. When a component is mounted or unmounted, the event handlers are simply added or removed from an internal mapping. When an event occurs, React knows how to dispatch it using this mapping. When there are no event handlers left in the mapping, React's event handlers are simple no-ops

This makes it seem like MDL might be messing with React's internal mapping of events, which causes my click on the element to become a no-op. But again, this is just a complete guess.

Does anyone have any ideas about this? I would prefer not to have to manually bind an event listener in componentDidMount for each of my components that use MDL Tooltips (like I did in the example JSBin I provided), but that's the solution I'm going with for now.

Also, since I was not sure if this was an MDL specific bug, I opted to post this question here instead of on their issues page. If anyone thinks I should post it there as well, let me know, and I can do that.

Thanks!

Michael Parker
  • 12,724
  • 5
  • 37
  • 58

2 Answers2

1

I faced this same issue too. I was trying to capture event clicks on a mdl-menu__item. And you are right in that React's synthetic event system is clashing. What happens is that if an event happens inside your React component, your component will be the last to hear of the event. My work around was circumvent reacts event and use a react component which helps to attach native events react-native-listener.

<NativeListener onClickCapture={this.onListClick}>
    <li className='mdl-menu__item' >
      {...}
    </li>
</NativeListener>

// This will be called by the native event system not react,
// this is in order to catch mdl-menu events and stop the menu from closing
// allowing multiple fields to be clicked
onListClick(field, event) {
  event.stopImmediatePropagation();
  // console.log('click');
}

My solution was for the mdl-menu but I'm sure it applies to the tooltip too.

enjoylife
  • 3,801
  • 1
  • 24
  • 33
  • Interesting, my `mdl-menu` items seem to work just fine. Thanks for the link though, I will try it out as soon as I get the chance. – Michael Parker Aug 07 '15 at 12:49
  • Also, there seems to be a bug with JSBin that sometimes causes it to not load anything but the react library on the html side. If you open it in an incognito window in Chrome (or the equivalent in any other browser), it will work. – Michael Parker Aug 07 '15 at 12:51
  • If you have onClicks on the dop level `mdl-menu` it does indeed work. But if you want to capture onClicks per mdl-menu_item and not have the menu close after a click I needed to stop the native propagation prior to mdl calling its close menu method – enjoylife Aug 07 '15 at 23:37
  • This is useful. I have encountered the same problem but with a tooltip on a file input element that, when clicked, opens the browser's file selection dialog. The solution to manually bind an event listener doesn't work here. Any ideas as to what might work? – Michael Pedersen Oct 01 '15 at 11:30
  • Could try an event.stopPropagation in the event listener? – enjoylife Oct 01 '15 at 20:49
  • Thank you for the suggestion Matt, but this doesn't help unfortunately. – Michael Pedersen Oct 02 '15 at 08:44
1

A little late but

componentHandler.upgradeAllRegistered();

gets dynamically loaded elements working.

Note: that if you move the target element via CSS position the tooltip does not render to the new position automagically, you will need to id it and position it too.

Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
  • It worked for me! You save me a lot of time. I put it into componentDidMount() and componentDidUpdate() functions and fixed all my problems. Thank you very much! – Genarito Nov 18 '16 at 17:43