JSX elements take event handlers much as DOM elements do, with some subtle differences in the syntax. JSX elements expect a function to be passed in curly brackets:
<button onClick={this.handleClick}>
Click me
</button>
The React binding expects this.handleClick
to be a function here. This would typically look something like:
class MyComponent extends React.Component {
handleClick(event) {
//...do something
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
If you write handlers like this as properties of the component, you're probably looking to make use of this
inside your handler somewhere, perhaps to access setState
(more about that later...). Just as ever in Javascript, the value of this
isn't inherently bound to the object where the function was originally defined.
If we add a reference to this
in the handler we've defined, we'll see that it is undefined
when referenced via the event callback.
class MyComponent extends React.Component {
handleClick(event) {
console.log(this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
Clicking on the button in this case will log undefined
. š£
Don't worry because there are a number of ways to fix this! We're going to be using the constructor function to do it in our examples.
This involves overwriting the constructor your component has inherited by extending the React.Component
class. The constructor
function is a native aspect of JavaScript classes. It is called whenever an instance of the class is instantiated using the new
keyword.
Note also that we want to make sure we preserve whatever functionality the constructor from the parent class contains. We can access the constructor of the parent via the keyword super
. We simply call super
immediately in our overriding constructor, passing in the initialization arguments -- in this case, props
.
After we've done the responsible thing and run the super
constructor, we can now do whatever other business we care to inside our new constructor function. In this case, we want to make sure that this.handleClick
is bound to this
:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
console.log(this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
This is a common pattern in Javascript that is not at all confined to React. It's useful any time you define a class, and need to preserve reference to this inside its class functions after they are passed around to be executed as callbacks outside of the original class context.
With that out of the way, our event handler should work now. Clicking the button should now log the component object itself.