開発者ドキュメント

Reactでイベントを処理する新しい方法

*「プロパティ初期化構文」*は実際よりも派手に聞こえます。 この一口サイズのチュートリアルでは、イベントハンドラーを作成するこの代替方法が、ボイラープレートを排除するのにどのように役立つかを確認してください。 constructor また、レンダリングでの軽薄なメモリ使用を防ぎます。

Facebookのドキュメントでは、次のようにイベント処理が行われていることがわかります。

// option 1
class Thing extends React.Component {
  constructor() {
    this.handleSmthng = this.handleSmthng.bind(this)
  }
  render() {
    <input onChange={this.handleSmthng}/>
  }
  handleSmthng(e) {
    // ...
  }
}

ES6クラスは自動的に提供しません this スコープ handleSmthng、そしてあなたは通常電話したくなるので this.setState または、コンポーネントで別のメソッドを呼び出す場合、「公式」の規則は、コンストラクターで常にすべてのイベントハンドラーをバインドすることです。 これは機能しますが、すぐにボイラープレートコードのように感じることがあります。


// option 2
class Thing extends React.Component {
  render() {
    <button onClick={() => this.handleSmthng('foo')}>
      ADD
    </button>
  }
  handleSmthng(arg1) {
    // ...
  }
}

このパターンは、オンラインのReactチュートリアルで人気が高まっているようです。 合格します this コンテキスト handleSmthng コンストラクターの定型コードを回避します。 このコンポーネントには状態がないので、コンストラクターも必要ありません。 このアプローチの動機は正しいと思います…しかし、わずかなパフォーマンスコストがあります。

矢印関数を使用すると、JavaScriptで常に新しい参照が作成され、アプリのメモリ使用量が増加します。 JavaScriptではメモリは安価ですが、Reactではレンダリングにコストがかかります。 矢印関数を子コンポーネントに渡すと、その矢印関数は新しいデータであるため、子コンポーネントは無差別に再レンダリングされます。 これは、大規模なReactアプリケーションで60fpsと50fpsを取得することの違いを意味する可能性があります。

「…しかし、このコールバックが下位コンポーネントへの小道具として渡された場合、それらのコンポーネントは余分な再レンダリングを行う可能性があります。」 Reactドキュメント

2つのバインド1つのクロージャー

1)ボイラープレートを回避し、2)余分な再レンダリングを引き起こさないイベントハンドラーを作成するためのはるかにクリーンな方法があります:プロパティ初期化構文! 派手な名前ですが、アイデアは本当に単純です…矢印関数を使用してイベントハンドラーを定義するだけです。 このような:

class TodoApp extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          ADD
        </button>
        <input onChange={this.handleInput}/>
      </div>
    );
  }
  handleClick = () => {
    // "this"
  }
  handleInput = (e) => {
    // "this", "e"
  }
}

あなたは2つのハンドラーを定義しました、そしてそれは本当に素晴らしく見えます。 ボイラープレートはありません。 読みやすい。 リファクタリングが簡単…引数を渡したい場合:

class TodoApp extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          ADD
        </button>
        <input onChange={this.handleInput}/>
        {
          this.state.todos.map((item) => {
            return (
              <li onClick={this.handleRemove(item.id)}>
                {item.text}
              </li>
            );
          });
        }
      </div>
    )
  }

  handleClick = () => {
    // "this"
  }

  handleInput = (e) => {
    // "this", "e"
  }

  handleRemove = (id) => (e) => {
    // "this", "e", "id"
  }
}

ブーム! 使用せずに引数を渡すことができます bind レンダリングメソッド、またはコンストラクターで! すべてが本当に刺激的でスパンに見えます。

矢印の機能を見ることに慣れていない場合、これはおそらく奇妙に見えます。 ES6では、太い矢印の構文により、1行のステートメントで中括弧を省略できることを覚えておいてください…暗黙的に return その行に何でも! これがバベルがトランスパイルする方法です handleRemove:

handleRemove: function (item) {
  return function (e) {
    // "item" AND "e" 🌈
  }
}

プロパティ初期化構文を使用するようにBabelを設定するには、「transform-class-properties」プラグインまたは enablestage-2がインストールされていることを確認してください。 「create-react-app」を使用している場合…すでにあります!

レンダリングで「バインド」または矢印機能を使用しないように指示するESLintルールがあります

プロパティ初期化構文を使用する利点

Facebookがドキュメントでこのパターンを「公式に」承認していないのは、ステージ2 ES6がまだ完成していないため、プロパティイニシャライザーが非標準と見なされているためです。 しかし create-react-app ジェネレーターはすでにステージ2を有効にしているので、近い将来、プロパティイニシャライザーがイベントハンドラーを定義するための事実上のものになる可能性が非常に高くなります。

プロパティイニシャライザーに慣れ、ハンドラーメソッドを定義するためにそれらを使い始めると、2つの注目すべき利点が得られます。

このCodePenをチェックして、プロパティ初期化構文の動作を確認してください

モバイルバージョンを終了