はじめに
現在のReactのバージョンは17ですが、バージョン16以前はevent poolingという機能がありました。(ReactNativeでは現在もあるみたいです)
event poolingがどういう機能だったのか、なぜ削除されたのかについて書いていきます。
Eventオブジェクトが使えなくなる機能?
const Component = () => {
const [text,setText] = useState("");
const onChange = (e) => {
setText(state => e.target.value);
}
return(
<input type="text" value={text} onChange = {onChange}
);
}
このコードはReact16以前では"target" is not defined
となり、思った通りに動作しません。
エラーを解決するには、e.persist()
が必要になります。
const onChange = (e) => {
e.persist();
setText(state => e.target.value);
}
event poolingの役割
なぜ、Eventオブジェクトが使えなくなるという不便な機能があったのでしょうか。
実は、event poolingにはReactのパフォーマンスを向上させるという役割があったのです。
event pooling のeventはDOMイベントのことを指します。
clickとかonchangeのようなイベントですね。
このDomイベントのオブジェクトをpoolingするわけです。
(object poolingデザインパターンです。オブジェクトを使いまわすことによってメモリの使用量を減らします。)
https://qiita.com/len/items/fe77090d5e63c32ae30e
Clickやonchangeのようなイベントだと、発火される回数は少ないですが、dragイベントのような高発火イベントだと大量にEventオブジェクトが生成されます。
Eventオブジェクトのガーベジコレクションによって、パフォーマンスが悪くなるのを防いでいるのです。
const onChange = (e) => {
setText(state => e.target.value);
}
setText
のような非同期の関数にコールバックすると、e.target.value
を処理するときにはEventオブジェクトは使いまわしのためにリセットされてます。
"target" is not defined
はこれが原因です。
e.persist()
はEventオブジェクトをリセットしないようにする関数です。
なぜ、React17で削除されたのか
event pooling が削除されたのは二つ理由があります。
一つはReactを使うときに混乱を招くこと
もう一つは、最新のJSエンジンではガーベジコレクションの最適化のためにevent poolingをしなくてもパフォーマンスにほとんど違いがないこと。
event poolingにもわずかではありますが、オーバーヘッドがあります。
将来的にはevent poolingをしない方がパフォーマンスが良くなるかもしれないそうです。