Binding handlers to elements in React - reactjs

I was learning React and wanted to deeply understand how handling events with event handlers work behind the scenes. Later, I came across this article https://hub.packtpub.com/how-to-perform-event-handling-in-react-tutorial/ explaining how event handling works behind the scenes. This article says that "When you assign an event handler function to an element in JSX, React doesn’t actually attach an event listener to the underlying DOM element. Instead, it adds the function to an internal mapping of functions. There’s a single event listener on the document for the page. As events bubble up through the DOM tree to the document, the React handler checks to see whether any components have matching handlers". By "it adds the function to an internal mapping of functions" does it mean that each component has its own internal mapping of functions? or does it mean that React takes all event handlers in an app overall and put all of those handlers in its internal mapping of functions?
Please guys help anyone. Please let me know if you are confused

Related

Mapbox click listener on base map fails when layers are added

I have a map within my react project where I want to use a click listener on the base map to find the coordinates of the point clicked. It has worked fine for a while now.
The problem is that I've added a few layers using clusters, some of which have click listeners, and now clicking anywhere on the map gives me the error "There is already a source with this ID." I think I get why - there's a click, but not on any of the layers.
I can't find any information on how to make the base map a layer, and thereby get an id for it to pass to the click listener. So my question is, how to I attach a click listener to the base map while still using layers that may also have click listeners, too.
So that was a big pain! What was happening was that I was passing a function down to the component that contained the click listener and that function changed the state of the parent component. Given that this is react, it caused the child components to rerender and thus Mapbox to error that there was already a source with the same id because the source had never been removed.
The solution was to wrap the code that added the source and attendant layers as a component, then create a cleanup component that contained removeSource (see here) and run that on unmounting. I'm using the new hooks api, so I'm running a setLayers function in the useEffect hook, then returning cleanup from useEffect, but I bet this sort of idea would work fine with componentDidMount and componentWillUnmount.

Mithril VM DOM diffing does not detect diff in attached event handler

This may not be a Mithril specific question but VM DOM diffing in general. While "redrawing" a page and you attach a new event handler, remove an event handler, or change the event handler associated with an event such as "onclick", it seems that the VM DOM diffing will not detect the change and I have to explicitly force a rerendering of the "real" DOM.
Is there a good pattern to handle these situations.
In Mithril specifically, onclick and all the on-handlers automatically trigger a redraw after the handler function has completed. However, if your onclick handler does real DOM manipulation (3rd party libraries such as jQuery or an animation suite) you need to use the config attribute:
http://lhorie.github.io/mithril/mithril.html#the-config-attribute
which gets called after the page has been rendered.
With regards to changing event handlers, it depends on when in the render cycle you make the change. I'd have to see some code. If it's not too inconvenient, calling redraw manually is not a bad thing. If the redraw strategy is "diff" you won't pay a penalty.
And lastly, if you are introducing your own events, consider using m.startComputation/m.endComputation in your event handlers. These provide much finer grain control and a redraw is automatically called.
http://lhorie.github.io/mithril/mithril.computation.html

attaching event handlers to react components using jquery

I know this is the proper way to do -
Attach handlers on react components using attributes such as onClick, onBlur etc.
If attaching custom events then attach them in componentDidMount so that it always gets attached on every rendering.
https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation
However, what happens when an event is attached to a DOM element using jquery ? Why am I not able to listen to those events ? I am attaching them out side componentDidMount. However the event handler should get trigerred the first time atleast ?
I was debugging some react code which was attaching an handler to it directly, but it was not trigerring the handler at all. Why was that ?
Without code example it's difficult to know for sure but more than likely you're trying to bind an event using jQuery to some react-generate DOM element. So depending where you do the bind, you're probably using a jQuery selector which returns no results because React hasn't rendered that element to the DOM at the time the selector is being run.
This is why, if you are going to use jQuery binding, you should make sure you do so as part of the component lifecycle that ensures the element is actually rendered to the DOM before you are trying to select it with jQuery. So that's why the recommendation is to put this kind of code inside componentDidMount and clean it up in componentWillUnmount.

React efficient way to bind event to many dom elements

Because we add onClick handlers directly to components... eg:
<button onClick={dosomething}>Click</button>
Is there an efficient way to do this (not adding an onClick to every element) when we're dealing with dozens of elements ?
For example, in my backbone apps I would just apply a handler to a class:
events:
'click .someclass': 'doSomething'
The backbone way seems much cleaner and easier to manage. Is there a way to emulate this behavior with React Components?
To add some perspective, I have say a dozen or more form elements that when any of them are changed, I want to potentially runs some logic. They could be text boxes, radio buttons, etc.
This optimization is not needed. It would if you were coding in other libraries like jQuery, but React does this automatically for you.
I quote:
Event delegation: 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. To learn more about why this is fast, see David Walsh's excellent blog post.
Seen here: https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html
You can apply the event handler to a common parent element instead and handle the event there:
<form onChange={this.handleChange}>
{/* ...form elements... */}
</form>
...where the event handler determines what to do based on the event object's .target:
handleChange(e) {
this.setState({[e.target.name]: e.target.value})
}
As a live example, I have an <AutoForm> component which uses this technique to render a <form> which handles extracting data from changed fields and the submitted form for you.

ExtJS 4 Track all events for a component

For debugging purposes I want to track all events for a certain component (combo, form, etc.) so I could see when and what events have fired for this component.
Is there a common approach to tracking all events without creating specific listeners?
You can use Ext.util.Observable for this purpose. Let's say the reference is myCombo:
Ext.util.Observable.capture(myCombo, function(){console.log(arguments)});
I use this one-liner quite often from the console to see the fired events.

Resources