Svelte - non-trivial intermediate variable within each loop

Viewed 437

How can I create variables inside Svelte's HTML like in React, or is it not at all how I am supposed to use Svelte. I know the example below is trivial but I'm thinking of a case where I really need some heavy logic for subArray (could not use a one liner)

React

<ul>
  {myArray.map((item) => {
    const subArray = item.items.filter(i = i > 0) // <- how can I have an intermediate variable like this in Svelte?
    return <li>{subArray.map(...)}</li>
  }}
</ul>

Svelte

<ul>
  {#each myArray as item}
    <li>
        {#each <complex-logic> as subItem}
        ...
        {/each}
    </li>
  {/each}
</ul>
2 Answers

If it's not too complicated you can directly modify the array inside {#each}

<script>
    let myArray = [
        {id: 1, items: [-2,-1,0,1,2]},
        {id: 2, items: [-20,-10,0,10,20]},
        {id: 3, items: [-222,-111,0,111,222]},
    ]
</script>

<ul>
    {#each myArray as item}
    <li>
        {item.id}:
        {#each item.items.filter(item => item >= 0) as subItem}
        {subItem}, 
        {/each}
    </li>
    {/each}
</ul>

or you could use the new {@const} directive

<ul>
    {#each myArray as item}
    {@const filteredItems = item.items.filter(i => i > 0)} 
    <li>
        {item.id}:
        {#each filteredItems as subItem}
        {subItem}, 
        {/each}
    </li>
    {/each}
</ul>

And if it's even more complicated, why not extract the logic into a function

    function complicatedModification(arr) {
        return arr.filter(item => item > 0)
    }
</script>

...
  {#each complicatedModification(item.items) as subItem}
        {subItem}, 
  {/each}
...

Here's a REPL with all the options

You can use the {@const} directive, which is a recent addition to Svelte. In your use case:

<ul>
  {#each myArray as item}
    {@const subArray = item.items.filter(i => i > 0)}
    <li>
        {#each subArray as subItem}
        ...
        {/each}
    </li>
  {/each}
</ul>
Related