React/ReactJS: Handling Events
There was once a habit of registering event handlers as HTML attributes as shown below.
<input type="radio" value="trillium" onclick="checkFlower()"
name="flower"/> Trillium<br/>
Once the click event occurs, the onclick
event handler calls the checkFlower()
function defined somewhere inside the <script>
element.
function checkflower(){
// do something
}
This practice is not recommended anymore, unless, of course, you are working on an archaic IE8/Opera 6 compatible web application which do not support the addEventListener()
method.
But in JSX, using inline event handlers happen to be a norm. Just that events in JSX are written in camelCase, like onClick
, onChange
, onMouseOver
, onPointerDown
, etc.
The above HTML tag with an event handler can be rewritten in JSX as:
<input type="radio" value="trillium" onClick={(e) => this.checkFlower(e)}
name="flower"/> Trillium<br/>
Now since any method defined inside an ES6 class inherits bind()
from the Function prototype, we can also write it as:
<input type="radio" value="trillium" onClick={this.checkFlower.bind(this)}
name="flower"/> Trillium<br/>
The checkFlower()
function is defined somewhere inside the component, and is known as a callback function (generally just "callback"), and e
is the synthetic event.
checkFlower(e) {
console.log('flower: ', e.target.value);
}
But again, such practice of binding in property or render is not encouraged because everytime the component renders, it creates a new function.
Binding of the callback function should be done in the constructor (ES6). Notice that bind()
is not used inside the JSX anymore.
class Flower extends React.Component {
constructor(props) {
super(props);
this.checkFlower = this.checkFlower.bind(this);
}
checkFlower(e) {
console.log('flower: ', e.target.value);
}
render() {
return (
<label>
<input type="radio" value="trillium"
onClick={this.checkFlower} name="flower"/>
Trillium
</label>
);
}
}
Now there is another way where we can do away with the mandatory bindings either inside the constructor or the JSX and do it in the method definition itself.
checkFlower = (e) => {
console.log('flower: ', e.target.value);
}
The syntax is elegant, but is still experimental (not-standardized).
Passing Extra/Additional Parameters
Also we may need to send additional parameters besides the synthetic event e
. As in JavaScript, we do this by sending a comma-separated list of arguments after this
.
<input type="radio" value="trillium"
onClick={this.checkFlower.bind(this, '3')}
name="flower"/> Trillium<br/>
Or if the binding is done properly inside the constructor:
constructor(props) {
super(props);
this.checkFlower = this.checkFlower.bind(this, '3');
}
But inside the callback, the synthetic event e
occurs last in the order of parameters.
checkFlower(petals, e) {
console.log("petals: ", petals, ', flower: ', e.target.value);
}