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/>
Great White Trillium
by Bernard B. ILarde.
CC BY-SA 3.0
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);
}