🌊

Svelteでリストが増えたら再レンダリングしたい!

2024/03/13に公開
2

こんにちは、フクロウです。

レンダリングのを調べたキッカケ

Svelteを試すためにでtodoアプリを作っていた時、todoリストを追加しても、画面表示されなくてどうしたものか...なかなか答えが出ず...

調べた結果、重要なのは「{#key}」を使うことでした。

keyで指定された変数の変更を検知して、{#key}で囲った場所のみを再レンダリングされるようです。

ソースコード

ソースコードをどうぞ!

<script>
  const dataList:number[] = [0]
  let dataCount:number = 0

  function push() {
    dataCount++;
    dataList.push(dataList.length)
  }
</script>

<button type="button" on:click={push}>追加</button>
{#key dataCount}
  {dataList}
{/key}

では、子コンポーネントの再レンダリングしたい場合はどうなるのか?
親コンポーネント

<script>
  import Item from './components/Item.svelte';
  const dataList:number[] = []
  let dataCount:number = 0

  function push() {
    dataList.push(dataList.length)
    dataCount = dataList.length
  }
</script>

<button type="button" on:click={push}>追加</button>
{#key dataCount}
  <Item dataList={dataList}>
{/key}

子コンポーネント

<script>
  // expotと書くだけでsvelteは親から子供へ値を受け渡せます。
  export let dataList:number[]
</script>

// あとはdataListを自由に使うだけ!
{#each dataList as data}
 {data}
{/each}

はい!これだけでできます。

余談

試してみて分かったのですが、{#key dataList.length} で変更検知をしてくれるかやってみましたが、dataList.pushでは変更検知はされませんでした。
{#key dataList.length} で変更検知を行う場合は、毎回、対象の配列を初期化しないとできません。

何かわからないことがあれば、コメントください。

Discussion

ryoppippiryoppippi

こんにちは

svelte4までは、変更をコンパイラに知らせるには代入を用いる必要があります。
そのため本文中にある通り、list.push(hoge)では変更は検知されないです
代入構文を使うとこうなります。

<script>
  let dataList = [0]

  function push() {
  dataList = [...dataList, dataList.length]
  }
</script>

<button type="button" on:click={push}>追加</button>
{dataList}

ちなみに来たるsvelte5では、runeを用いることで明示的に変化する変数をコンパイラに伝えることができるため.pushを用いても変更は検知されます

<script>
  let dataList = $state([0])

  function push() {
  dataList.push(dataList.length)
  }
</script>

<button type="button" onclick={push}>追加</button>
{dataList}

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAEz2OQWrDMBBFrzIMXcRgmq6Nbei-N8hk4crjRlQZCWtUKEIX6Cl6kZDTBHKMooZk-f6f__9kXKzjiN0uo0xHxg5fQ8AW9TtUiF_slLHF6NNqqtJHs9qgIwmAY4V50unNRoUBnqJOypvdy74hqf6SxKj1AiHFw6aBTEJKeo88_8sPciwfemhqsJD028cQSf-eVL1A_WogvBEheOmMs-ZzyLWqjNfz6fLz229vByNJvrcXEmzx6Ge7WJ6x0zVx2Zc_gpjTdwABAAA=