Svelteのライフサイクルのtick()の使い方

Svelteのtick()とは

Svelteのtick()は非同期関数で、次のDOM更新サイクルが完了を待機したいときなどに使用されます。

tick()を使用するとDOM更新が保証されます。

Svelteの公式ドキュメントでは以下のように書かれていますが、この内容で理解するのは難しいです。

※ 以下のコードだとawait tick()がなくても結果が変わらないので、理解しづらい。

promise: Promise = tick()

保留中の state の変更が適用されると resolve する promise を返します。もしくは何も保留していない場合に、その次のマイクロタスクで実行されます。

<script>
  import { beforeUpdate, tick } from 'svelte';

  beforeUpdate(async () => {
    console.log('the component is about to update');
    await tick();
    console.log('the component just updated');
  });
</script>

Svelteのtick()の使い方

例えば以下のようにボタンをクリックするとcountが1ずつ加算されて、console.logでid="result"のテキストを表示させるコードがあるとします。

<script>
  let count = 0

  function increment() {
    count += 1
    const result = document.getElementById('result').textContent
    console.log(result)
  }
</script>

<button on:click={increment}>
  Click
</button>

<p id="result">{count}回目</p>

Svelteのtick()なし サンプル

コードだけ見ると問題ないようにも見えますが、実行すると1回目、2回目、…とWebページ上の表示は変わりますが、console.logは0回目、1回目、…と表示されてしまいます。

これはDOM更新される前に id="result" を取得していることが原因です。

tick() を使用すると次のDOM更新サイクルが完了を待機できるので、DOMが更新されてから処理を行うことができます。

※ tick()は非同期関数のためawaitを付けるので、increment関数にはasyncが必要です。

<script>
  import { tick } from 'svelte'
  let count = 0

  async function increment() {
    count += 1
    await tick()
    const result = document.getElementById('result').textContent
    console.log(result)
  }
</script>

<h1>Svelteのtick()あり サンプル</h1>
<p>Consoleも確認してください。</p>

<button on:click={increment}>
  Click
</button>

<p id="result">{count}回目</p>

Svelteのtick()あり サンプル