By Ran Bar-Zik | 11/5/2018 | General |Beginners

React Components with Events

React Components with Events

In our previous article on React, we covered state and how we can use it to store data inside of components. As an example, we saw how to activate a method automatically once every second. But in reality, in a practical application, we’ll want to be able to make changes to the state through a user action. For instance, user clicks that will do something like change the state or call some other function that will cause a change to the state. One way or another, we’re going to need events—responses to things that the users do in our components.

 

So how shall we demonstrate? Let’s take a look at a React application that counts clicks. It has two components: ClickCounterDisplay that is in charge of the view and the CSS, and inside of it, there’s another little ol’ component called ClickCounter. At the moment, all it has inside is the initialization state with clicksNumber at 0.

 

The HTML will look like this:

0 clicks react component

0

Clicks

This is all well and good, but pretty boring because the component is never going to change. I want to add a button with a plus sign that will add to the state every time it gets clicked on causing the number to go up by one.

 

The first thing I need to do is add a method that will increase this.state.clicksNumber by 1 inside the ClickCounter component which contains that data. OK, this is pretty easy using this.setState:

class ClickCounter extends React.Component {
 constructor(props) {
   super(props);    
   this.state = {
     clicksNumber: 0,
   };
 }
 clickHandler() {
   this.setState({clicksNumber: this.state.clicksNumber+1});
 }
 render() {
   const content = <div>{ this.state.clicksNumber }</div> // This is JSX
   return content;
 }
}

But the clickHandler function won’t really work without someone calling it. So who will call it? Just a simple button with an event called onclick. Be honest, you thought it was gonna be a lot more complicated than that, right? We’ll add the button and with onclick we’ll call the function clickHandler. Since we’re going outside of the scope, we mustn't forget to add bind. Here’s how it all looks:

class ClickCounter extends React.Component {
 constructor(props) {
   super(props);    
   this.state = {
     clicksNumber: 0,
   };
   this.clickHandler = this.clickHandler.bind(this);
 }
 clickHandler() {
   this.setState({clicksNumber: this.state.clicksNumber +1});
 }
 render() {
   const content = <div>
           { this.state.clicksNumber }
            <button onClick={this.clickHandler}>+</button>
   </div>
   return content;
 }
}

 And it even works.

 

But just hold your horses, there’s more in store here. It’s important to note that onClick is not a native browser event. We’re using JSX here and not HTML. In the end, it all gets rendered to JavaScript, but that onClick is really a synthetic event and not a ‘real’ one that comes from the DOM. Why? It has to do with implementation (I won’t get too deep into it here) but it’s pretty important to know. Why? Because if I want to assign an event to a React component, it won’t work. Here’s an example, ‘cause I know you were gonna ask. So let’s replace our dinky little JSX button:

<button onClick={this.clickHandler}>+</button>

 I’ll create a component that only has a button in it and I’ll try to assign an event to it:

class ClickCounterDisplay extends React.Component {
 render() {
   const bigStyle = {
     backgroundColor: 'black',
     borderRadius: 10,
     color: 'silver',
     fontSize: '42px',
     textAlign: 'center',
     width: 250,
   };
   const smallStyle = {
     color: 'gold',
     fontSize: '25px',
   };
   return <div style={bigStyle}>
       <ClickCounter />
       <div style={smallStyle}>Clicks</div>
     </div>
 }
}
 
class SomeButton extends React.Component {
 render() {
   return <span><button>+</button></span>
 }
}
 
class ClickCounter extends React.Component {
 constructor(props) {
   super(props);    
   this.state = {
     clicksNumber: 0,
   };
   this.clickHandler = this.clickHandler.bind(this);
 }
 clickHandler() {
   this.setState({clicksNumber: this.state.clicksNumber +1});
 }
 render() {
   const content = <div>
           { this.state.clicksNumber }
            <SomeButton onClick={this.clickHandler} />
   </div>
   return content;
 }
}
 
const target = document.getElementById('content');
ReactDOM.render(
 <ClickCounterDisplay />,
 target
);

As you can see, I created a component called SomeButton which I call in JSX, and try to assign an event to it. So what’s the problem? Problem is, it won’t work. And why you ask? Because onClick is a synthetic event and not a ‘real’ event. You can’t assign it directly to a React component. So how do we do it? It’s really quite easy actually—we just use handler. In other words, we pass the function that was called from outside as a parameter.

 

The SomeButton component will look like this:

 

class SomeButton extends React.Component {

 render() {

   return <span><button onClick={this.props.clickHandler}>+</button></span>

 }

}

I get clickHandler from outside as a parameter. How do I pass it? Just like this:

<SomeButton clickHandler={this.clickHandler} />

It looks a little crooked but it beats the hell out of the alternative which is to use real events which would have a heavy cost in implementation. If we use events, we need to kill them when the component is gone, which is a good habit to get into.

 

Previous Article: React Stateful Components Next article: The React Lifecycle

 

 About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen. 

By Ran Bar-Zik | 11/5/2018 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now