There are many events that get triggered by the system such as clicking, page loading, keypress, scrolling, etc. React provides event handling which is similar to event handling on DOM elements. React events are synthetic events, a cross-browser wrapper around the browser’s native event. It works the same across all browsers.
React event handling is similar to HTML with some changes in syntax, such as:
React uses camelCase for event names while HTML uses lowercase.
Instead of passing a string as an event handler, we pass a function in React.
Example:
In HTML:
1 2 3
<button onclick="clickHandler()"> Clicked </button>
In React js
1
2
3
<button onClick={clickHandler}>
Clicked
</button>
Also, like in HTML, we cannot return false to prevent default behavior; we need to use preventDefault to prevent the default behavior.
In HTML
1 2 3
<form onsubmit="console.log('clicked'); return false"> <button type="submit">Submit</button> </form>
In React js
1
2
3
4
5
6
7
8
9
10
11
12
function Form() {
function handleClick(e) {
e.preventDefault();
console.log('Clicked');
}
return (
<form onSubmit={handleClick}>
<button type="submit">Submit</button>
</form>
);
}
Changing state in onClick event listener:- We have to call this.setState method (for class component) or useState hook (for functional component) inside the onClick handler to update state value. The example below shows how it is implemented using class component.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class EventBind extends React.Component {
constructor(props) {
super(props);
this.state = {
steps: 0
};
/*ignore bind for now we will explain about binding soon.
Just know that it is necessary for right working of 'this' keyword*/
this.clickHandler = this.clickHandler.bind(this);
}
clickHandler() {
this.setState({
steps: this.state.steps + 1
});
}
render() {
return (
<>
<div>{this.state.steps}</div>
<button onClick={this.clickHandler}>Click</button>
</>
);
}
}
If you want to do the same thing with a functional component then you can refer to the following example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function EventBind() {
const [steps, setSteps] = useState(0);
/*Note the fact that we are using the arrow function here.
We will discuss about it in binding section soon*/
const clickHandler = () => {
setSteps(steps + 1);
};
return (
<>
<div>{steps}</div>
<button onClick={clickHandler}>Click</button>
</>
);
}
If you have used JavaScript before then you are familiar with the ‘this’ keyword and how it works. If you don’t bind the ‘this’ keyword with the event handler then it will point to undefined in the callback. This is JavaScript-specific behavior and is not related to React. There are five different ways to bind ‘this’ keyword to the event handler, listed below.
We can bind the ‘this’ keyword to the event handler in the constructor when using the class component. This is the most common way to handle this problem.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class EventBind extends React.Component {
constructor(props) {
super(props)
this.state = {
message: 'Event Bind'
}
this.clickHandler = this.clickHandler.bind(this)
}
clickHandler() {
this.setState({
message: 'change state'
})
}
render() {
return (
<>
<div>{this.state.message}</div>
<button onClick={this.clickHandler}>Click</button>
</>
)
}
}
We can use the arrow function as the function in the event listener. In this case we don’t need to bind the ‘this’ keyword. But this method has its own drawbacks.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class EventBind extends React.Component {
constructor(props) {
super(props)
this.state = {
message: 'Event Bind'
}
}
clickHandler() {
this.setState({
message: 'change state'
})
}
render() {
return (
<>
<div>{this.state.message}</div>
<button onClick={()=>this.clickHandler()}>Click</button>
</>
)
}
}
Bind the ‘this’ keyword directly when passing a function in the event listener.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class EventBind extends React.Component {
constructor(props) {
super(props)
this.state = {
message: 'Event Bind'
}
}
clickHandler() {
this.setState({
message: 'change state'
})
}
render() {
return (
<>
<div>{this.state.message}</div>
<button onClick={this.clickHandler.bind(this)}>Click</button>
</>
)
}
}
Make the event handler function with an arrow function. In this case, we don’t need to bind the ‘this’ keyword.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class EventBind extends React.Component {
constructor(props) {
super(props)
this.state = {
message: 'Event Bind'
}
}
clickHandler = () => {
this.setState({
message: 'change state'
})
}
render() {
return (
<>
<div>{this.state.message}</div>
<button onClick={this.clickHandler}>Click</button>
</>
)
}
}
Here is a second example for binding using an arrow function.
1
2
3
4
5
6
7
8
9
10
class EventBind extends React.Component {
clickHandler = event => {
console.log("Clicked")
}
render() {
return (
<button onClick={this.clickHandler}>Click</button>
)
}
}
If we use the functional component along with the arrow function then we don’t need to bind ‘this’ keyword. The following example demonstrates this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//using functional component with arrow function
const EventBind = () => {
const [steps, setSteps] = useState(0);
function clickHandler() {
setSteps(steps + 1);
}
return (
<>
<div>{steps}</div>
<button onClick={clickHandler}>Click</button>
</>
);
}
We can call multiple functions inside the onClick event handler in React. To do so we just need to call them one by one. Following is an example which demonstrates this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class EventBind extends React.Component {
printMessage() {
console.log("This is a message");
}
showAlert() {
alert("button was clicked");
}
clickHandler() {
this.printMessage();
this.showAlert();
}
render() {
return (
<button onClick={this.clickHandler.bind(this)}>Click</button>
);
}
}
Sometimes we need to pass an extra parameter to the event handler. We can do that using two of the methods above.
Example:
Pass the event and an extra parameter, like id, in the event listener using the arrow function.
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
Or we can use them by directly binding them when passing the event handler in the event listener and passing an extra parameter there.
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
React event handling is similar to that of HTML event handling, only with some syntax difference. We should make sure ‘this’ keyword is working, which is JavaScript behavior, not React-specific behavior. We can pass an extra parameter along with the event handler using two different syntaxes. We have discussed event handling using click handlers but there are many other event handlers similar to HTML event handlers, all of the above rules apply to them as well.