こんにちは。AG-Boost事業部開発部の石崎です。最近 onChangeのコールバックが続けざまに呼びされるのをパフォーマンス改善をするのに、lodashのdebounceを使用して解決しました。今回使用したのはdebounceですが、似たようなものでthrottleもあるのでそちらの紹介もします。
debounceとは
イベントを呼び出し後、次のイベントまで指定した時間が経過するまではイベントを発生させないようにする処理。
例えば、指定した時間を1000msecとした場合、300msec後にイベントが発生したら実行タイミングが1000msec後にリセットされ、1000msec以上時間が経過しなければイベントが発生しないような感じになります。
event呼び出し (0msec) -> event呼び出し(300msec) この時イベントが発生するのは1300msec後(待機時間を1000msecとした場合)
throttleとは
イベントを呼び出し後、指定した時間が経過するまではイベントを発生させないようにする処理。
event呼び出し (0msec) -> event呼び出し(300msec) -> event呼び出し(1000msec) この時イベントが発生するのは0msec後と1000msec後(待機時間を1000msecとした場合)
元のコード
import React from 'react'; export default () => { const onChange = (e) => { // 入力された文字を使った何らかの処理 console.log(e.target.value); }; return ( <input type="text" onChange={onChange} /> ); }
こちらのコードでinputにabcdefgと連続して入力すると
a ab abc abcd abcde abcdef abcdefg
のようにログが出るので、入力が変化されるたびにコールバックが実行されていることがわかります。
変更したコード(debounce)
import React from 'react'; import _ from 'lodash'; export default () => { const onChange = _.debounce((e) => { // 入力された文字を使った何らかの処理 console.log(e.target.value); }, 1000); return ( <input type="text" onChange={onChange} /> ); }
こちらのコードでinputにabcdefgと連続して入力すると
abcdefg
のように最後の入力から1000msec後に1度だけコールバックが実行されます。 当然1文字1文字の入力の間は1000msec以上間隔を開けて入力すれば、元のコードと同じログが出ます。
変更したコード(throttle)
import React from 'react'; import _ from 'lodash'; export default () => { const onChange = _.throttle((e) => { // 入力された文字を使った何らかの処理 console.log(e.target.value); }, 1000); return ( <input type="text" onChange={onChange} /> ); }
こちらのコードでinputにabcdefgと連続して入力すると
a abcd abcdefg
のように1000msec間隔でログが出力されます。
終わりに
debounceを使うことで、event中に呼ばれるAPIの回数を大幅に減らすことができました。今回は例として待機時間を1000msecで行いましたが、実際にはもっと短い時間で問題ありません。