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/>		
				
			
trillium flower 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);
					  }