Reactのイベントコールバックで非同期にeventオブジェクトを参照する

Oct 12, 2016

Reactでイベントコールバックのeventオブジェクトに非同期でアクセスしようとするとエラーが出て怒られる。例えば、setStateの第二引数のコールバック内でeventを参照しようとした時とか。

function clickHandler(event) {
  this.setState({
    foo: 'bar'
  }, function () {
    console.log(event.target.value); // error
  });
}

なぜ参照できないか

ReactのドキュメントのEvent poolingに書いてあった。

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.

簡単に説明すると、eventオブジェクトはReactによってSyntheticEventオブジェクトとしてラップされていて、パフォーマンスのために使いまわしてますよ。その関係で、イベントコールバックが実行され終わったら全てのプロパティをnullにするから、非同期ではアクセスできませんよ、ということらしい。

解決策

これもドキュメントの同じ項に書かれている。

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

非同期でアクセスしたかったらevent.persist()使ってくれ、と書かれている。なのでイベントコールバックの中で呼んであげれば非同期でeventを参照することができる。

function clickHandler(event) {
  event.persist();

  this.setState({
    foo: 'bar'
  }, function () {
    console.log(event.target.value); // ok
  });
}