グローバルにteardown
する
こんなときに使いたい
Turbolinksは、ページから離れる前にページの情報をキャッシュします。同じページを再度開くと、最初にキャッシュされたバージョンがプレビューに表示されて、続いてコンテンツがリフレッシュされます。
このため、キャッシュする前の状態に過渡的な変更を加えると、そのコンテンツは消えてしまいます。
この状況を修正するには、DOMを操作するコントローラすべてにteardown
メソッドを追加して、変更をロールバックする必要があります。以下のスニペットをたとえばapp/javascript/packs/application.jsに追加すると、このメソッドを実装するすべてのコントローラのステートをグローバルにリセットできます。
// app/javascript/packs/application.js
document.addEventListener('turbolinks:before-cache', () => {
application.controllers.forEach(controller => {
if (typeof controller.teardown === 'function') {
controller.teardown()
}
})
})
// app/javascript/controllers/any_controller.js
export default class extends Controller {
connect() {
// ...
}
teardown() {
this.element.classList.remove('play-animation')
}
}
そうする理由
Stimulusコントローラ内のdisconnect
は、いわゆるティアダウン(teardown: 終了処理)コードに関連しますが、一般的なライフサイクルコールバックからは、コントローラやその要素自身と無関係なコードを排除すべきという考え方もあります。
Turbolinksに関連するティアダウンロジックに独自のライフサイクルメソッドを持たせることで、ロールバックが厳密に1箇所でのみ行われるようになり、どのコントローラもこの振る舞いを選択することもしないこともできるようになります。
注意
Stimulusのすべてのコントローラには既にdisconnect
関数が組み込まれているのに、わざわざティアダウンメソッドをもう1つ追加する理由が本当にあるのかという議論もあります。アプリケーションでのTurbolinksの利用法や、Turbolinks関連のティアダウンロジックが他のconcernとどのぐらい異なるかにもよりますが、この振る舞いを重複させない方がよいかもしれません。
概要
元サイトの許諾を得て翻訳・公開いたします。