Stimulusコントローラでdisconnectを書く理由(翻訳)
Stimulusのdisconnect
メソッドは、initialize
とconnect
に続く第3のライフサイクルメソッドです。
disconnect
が呼び出されるタイミングは、DOMからコントローラが削除されるときです。StimulusはDOM要素をトラッキングするためにMutationObserver
を使っています。
disconnect
メソッド内では、ティアダウン(teardown: 終了処理)やクリーンアップなど、好きなことを実行できます。実行の理由は、メモリリークの防止からブラウザのパフォーマンス維持や予期しない副作用の防止まで、さまざまです。
いくつか例を見てみましょう。
export default class extends Controller {
connect() {
this.interval = setInterval(() => {
console.log("Run, Forrest, run!");
}, 1000);
}
}
上のinterval
を以下のようにクリーニングしないと、バックグラウンドでずっと動き続けてメモリリークが発生します。
export default class extends Controller {
disconnect() {
clearInterval(this.interval);
}
}
あるいは、以下のようにCodeMirrorなどのサードパーティライブラリを使っているとします。
import { EditorView } from "@codemirror/view"
export default class extends Controller {
connect() {
this.editor = new EditorView();
}
}
このライブラリのクリーンアップも以下のようにシンプルに行えます。
import { EditorView } from "@codemirror/view"
export default class extends Controller {
disconnect() {
this.editor?.destroy();
}
}
このクリーンアップを怠ると、this.editor
の新しいインスタンスがそれぞれ独自のステートを持ってしまい、エディタのDOM要素がメモリ上に残ってしまう可能性があります。
ブラウザを壊す可能性のある別の例も見てみましょう。💥
export default class extends Controller {
connect() {
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
this.videoStream = stream;
this.element.srcObject = stream;
});
}
}
このビデオストリームを止めておかないと、バックグラウンドでずっと実行中のままになります。実行中のビデオストリームが複数になるとCPU使用率が上昇して、ブラウザがメモリ不足でクラッシュする可能性があります。
ではdisconnect
を追加してみましょう。
export default class extends Controller {
disconnect() {
this.videoStream.getTracks().forEach(track => track.stop());
}
}
皆さんがこれらのサンプルを参考にして、きちんと後片付けをするよき市民になれますように!😊
概要
元サイトの許諾を得て翻訳・公開いたします。