Handling Events In ReactJS
Handling events in ReactJS is very similar to how it’s done on DOM elements. There are a few differences though.
Event names are camelCased, so instead of onclick
you have to use onClick
:
<button onclick="toggleDropdown()">Categories</button>
// DOM example
<button onClick={toggleDropdown}>Categories</button>
// JSX example
Also as you can see event handler function instead of a string.
Event Handlers
Event handlers are defined as methods on class based components:
class ExampleComponent extends React.Component {
handleClick(e){
// ... code to be executed on click
}
}
All handlers receive an event
object that adheres, cross-browser, to the W3C UI Events spec.
Reference To this
If you are going to use reference do this
in your event handler, for example to call this.setState
- don’t forget to bind it.
class ExampleComponent extends React.Component {
state = {counter: 0}
increment(e){
this.setState({counter: this.state.counter + 1})
// Here you'll get an error because of wrong
// reference to `this`
}
render(){
return <button onClick={this.increment}>Increment</button>
}
}
You have several options on how to bind this
:
Bind In Render
You can use Javascript method bind
right where you assign your event listener to make it keep correct reference to this
.
render(){
return <button onClick={this.increment.bind(this)}>Increment</button>
}
Downside of this method is that increment
function will be allocated on each render. In some cases it will lead to performance drop.
Arrow Functions In Render
Alternatively you can use arrow functions. You can use them in render()
method:
render(){
return <button onClick={e => this.increment(e)}>Increment</button>
}
This will cause same problems as with binding functions in render()
.
Bind In Constructor
You can avoid allocating function on every render if you call bind
inside of the constructor
.
class ExampleComponent extends React.Component {
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
}
//...
This is preferred way of binding.
Arrow Functions In Class Property
If you use babel
with the property initializing syntax (enabled by default in create-react-app
) you can define your handlers as arrow functions on your class fields.
class ExampleClass extends React.Component {
// ...
increment = e => {
this.setState({counter: this.state.counter + 1})
// Here it will have correct reference to `this`
}
// ...
}