When reading Svelte 3 documentation of the {#each} keyword, it isn't clear how to correctly handle the case where the variable we want to iterate on is null or undefined.
A common use case is listing the result of an object of type Promise<MyItem[]>. We could imagine for example that this promise represents the result of an HTTP request. We would first initialized the promise to null as a way to communicate that we didn't fetch any result yet.
A basic version that doesn't handle empty or false-y results would look like this:
<script lang="ts">
import { storeRequestResults } from "./stores"
</script>
<ul>
{#await $storeRequestResults}
<p>loading...</p>
{:then result}
{#each result as item}
<li>{item}</li>
{/each}
{:catch error}
<pre>{error}</pre>
{/await}
</ul>
Unfortunately when {:then result} is facing a null or undefined value, the Svelte template will fail with a runtime error: "Uncaught Error: {#each} only iterates over array-like objects".
The error message is clear enough, #each only deals with arrays.
We could fix it by changing our initialization value, or add an {#if result} block around the {#each}, but there is a simplest solution that only has very little downside: use the || operator to default to an empty array.
That does look like this:
{#await $storeRequestResults}
...
{:then result}
<!-- 1. Use the logical OR operator to default to an empty array if 'result' is false-y
👇 -->
{#each result || [] as item}
<li>{item}</li>
<!-- 2. Use the `:else` clause to handle the case where the array is empty -->
{:else} <!-- 👈 -->
<li>No items found<li/>
{/each}
{:catch error}
...
{/await}
I hope that helps some of you, it's a nice trick to know!
Svelte 3 - Handle null and undefined when iterating on arrays
August 27th 2020When reading Svelte 3 documentation of the
{#each}
keyword, it isn't clear how to correctly handle the case where the variable we want to iterate on isnull
orundefined
.A common use case is listing the result of an object of type
Promise<MyItem[]>
. We could imagine for example that this promise represents the result of an HTTP request. We would first initialized the promise tonull
as a way to communicate that we didn't fetch any result yet.A basic version that doesn't handle empty or false-y results would look like this:
Unfortunately when
{:then result}
is facing anull
orundefined
value, the Svelte template will fail with a runtime error: "Uncaught Error: {#each} only iterates over array-like objects".The error message is clear enough,
#each
only deals with arrays.We could fix it by changing our initialization value, or add an
{#if result}
block around the{#each}
, but there is a simplest solution that only has very little downside: use the||
operator to default to an empty array.That does look like this:
I hope that helps some of you, it's a nice trick to know!