Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

Stimulusコントローラでdisconnectを書く理由(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

Stimulusコントローラでdisconnectを書く理由(翻訳)

Stimulusのdisconnectメソッドは、initializeconnectに続く第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());
  }
}

皆さんがこれらのサンプルを参考にして、きちんと後片付けをするよき市民になれますように!😊

関連記事

Better Stimulusガイド:アーキテクチャ1: アプリケーションコントローラ(翻訳)

Tailwind CSS: 開発者が知っておきたいデリケートなUIデザインの便利技11種(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。