Scope of Svelte variables in await blocks

Viewed 55

Let's say we have this very common code:

{#await myPromise then myResult}

  <DataTable rows={myResult.rows}/>

{\await}

Suppose you need to update the returned rows at a later moment, or any other data from the promise's result.

The question: is there any simple way to store a reference to myResult or to their properties in order to be handled in the script block? I'm using two workarounds, but there must be a simpler way.

Workaround #1: don't use an await block at all. Use the fetch().then() syntax and handle it all at the script block. Contrived, but it works.

Dirty workaround #2: create a stupid function that takes a lambda an returns always an empty string. Call that stupid function like this:

{#await myPromise then myResult}

  {myStupidFunction(() => { rowsInScript = myResult.rows; })}

  <DataTable rows={myResult.rows}/>

{\await}

Since the function returns nothing, it doesn't affect the HTML section.

I hope there's a more elegant way to achieve this, nevertheless.

1 Answers

As of current there isn't a very straightforward way to do this no.

Your option 1 is the most common one, but with a twist where you assign your data to a variable in your promise and then throw away the returned values in the await block.

<script>
  let results;
  async function myPromise() {
    results = await fetch()
  }
</script>
{#await myPromise then _}
  ...
{/await}

Your option 2 looks extremely dirty to me, I wouldn't do that.

But if those rowsInScript are only to be used within the await block, you could maybe use {@const} ?

{#await myPromise then myResult}
  {@const rowsInScript = myResult.rows}
  ...
{\await}

One other approach (less common as it's a bit dubious) is too have a component fetch the data and then pass this data to another component.

{#await myPromise then results}
   <DisplayComponent {...results} />
{/await}

(For some use cases you could make this fetching one abstract and use slots to make it a bit more flexible)

Related