Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 25 additions & 16 deletions content/docs/handling-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ redirect_from:
Handling events with React elements is very similar to handling events on DOM elements. There are some syntactic differences:

* React events are named using camelCase, rather than lowercase.
* With JSX you pass a function as the event handler, rather than a string.
* With TSX you pass a function as the event handler, rather than a string.

For example, the HTML:

Expand All @@ -23,7 +23,7 @@ For example, the HTML:

is slightly different in React:

```js{1}
```typescript
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please maintain the highlited lime numbers feature

<button onClick={activateLasers}>
Activate Lasers
</button>
Expand All @@ -39,7 +39,7 @@ Another difference is that you cannot return `false` to prevent default behavior

In React, this could instead be:

```js{2-5,8}
```typescript
function ActionLink() {
function handleClick(e) {
e.preventDefault();
Expand All @@ -60,8 +60,11 @@ When using React you should generally not need to call `addEventListener` to add

When you define a component using an [ES6 class](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes), a common pattern is for an event handler to be a method on the class. For example, this `Toggle` component renders a button that lets the user toggle between "ON" and "OFF" states:

```js{6,7,10-14,18}
class Toggle extends React.Component {
```typescript
interface IOwnProps {}
interface IState {}

class Toggle extends React.Component<IOwnProps, IState> {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
Expand All @@ -70,13 +73,13 @@ class Toggle extends React.Component {
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
private handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}

render() {
public render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
Expand All @@ -93,21 +96,24 @@ ReactDOM.render(

[Try it on CodePen.](http://codepen.io/gaearon/pen/xEmzGg?editors=0010)

You have to be careful about the meaning of `this` in JSX callbacks. In JavaScript, class methods are not [bound](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) by default. If you forget to bind `this.handleClick` and pass it to `onClick`, `this` will be `undefined` when the function is actually called.
You have to be careful about the meaning of `this` in TSX callbacks. In JavaScript, class methods are not [bound](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) by default. If you forget to bind `this.handleClick` and pass it to `onClick`, `this` will be `undefined` when the function is actually called.

This is not React-specific behavior; it is a part of [how functions work in JavaScript](https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/). Generally, if you refer to a method without `()` after it, such as `onClick={this.handleClick}`, you should bind that method.

If calling `bind` annoys you, there are two ways you can get around this. If you are using the experimental [public class fields syntax](https://babeljs.io/docs/plugins/transform-class-properties/), you can use class fields to correctly bind callbacks:

```js{2-6}
class LoggingButton extends React.Component {
```typescript
interface IOwnProps {}
interface IState {}

class LoggingButton extends React.Component<IOwnProps, IState> {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
private handleClick = () => {
console.log('this is:', this);
}

render() {
public render() {
return (
<button onClick={this.handleClick}>
Click me
Expand All @@ -121,13 +127,16 @@ This syntax is enabled by default in [Create React App](https://github.com/faceb

If you aren't using class fields syntax, you can use an [arrow function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) in the callback:

```js{7-9}
class LoggingButton extends React.Component {
handleClick() {
```typescript
interface IOwnProps {}
interface IState {}

class LoggingButton extends React.Component<IOwnProps, IState> {
private handleClick() {
console.log('this is:', this);
}

render() {
public render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Expand Down
2 changes: 1 addition & 1 deletion content/docs/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
- id: state-and-lifecycle
title: State and Lifecycle (TS✓)
- id: handling-events
title: Handling Events
title: Handling Events (TS 70%)
- id: conditional-rendering
title: Conditional Rendering
- id: lists-and-keys
Expand Down