イベントプーリング
React ではイベントハンドラでは Synthetic イベントオブジェクトが渡されます。この点については次の記事で説明しています。
さて、この Synthetic イベントオブジェクトを使う際には気をつけないといけない点があります。
それがイベントプーリングです。
実はパフォーマンスを向上させるために、Synthetic イベントオブジェクトはあらかじめ作成されてプールされています。 言い換えると、Synthetic イベントオブジェクトは「作りおき」されています。
作りおきされて、そのオブジェクトのプロパティだけ差し替えられて、次々と使われるようになっています。この仕組みにより、 無駄なオブジェクトの生成が回避でき、パフォーマンスが向上します。
しかし、Synthetic イベントオブジェクトを使うのに少し注意が必要になります。
具体例として、次の例を見てください。
次のプログラムでは、テキストボックスに入力した文字がコピーされて、その直下に書き出されています。
このコードは次のように書いています。
import React from 'react';
export default class CCText extends React.Component {
constructor(props){
super(props);
this.state = { s: "" };
this.onChange = this.onChange.bind(this);
}
onChange(e){
var v = e.target.value;
this.setState((prevState, props) => {
return { s: v }
});
}
shouldComponentUpdate(nextProps, nextState){
return true;
}
render() {
return (
<div>
<input type="text" onChange={this.onChange}/>
<div>{this.state.s}</div>
</div>
);
}
}
状態の利用方法と、イベントハンドラの呼び出し方法については、「React コンポーネントの状態とイベント処理」を参考にしてください。
さて、ここのポイントは onChange です。
onChange(e){
var v = e.target.value;
this.setState((prevState, props) => {
return { s: v }
});
}
onChange では e.target.value として、テキストボックス内の値を取り出して、変数v に保存してから、 setState を呼び出しています。
もし、setState の中で直接 e.target.value を参照しようとすると、次のように "TypeError: Cannot read property 'value' of null" のエラーが発生します。
これは Synthetic イベントオブジェクト e の target プロパティが、既に null にクリアされてしまっているからです。
setState でも e を維持するには、次のように persist() メソッドを呼びます。
onChange(e){
e.persist();
this.setState((prevState, props) => {
return { s: e.target.value }
});
}
以上、ここでは具体例を挙げて、Synthetic イベントオブジェクトのイベントプーリングについて説明しました。