I have a component which needs to wait for an async function, loadSvx
to load data from an .svx file. I used an #await
block for this, and :then
store the result in svx
.
svx.meta
then holds the properties of the 'Front Matter' listed in the .svx
file. which I want to pass to the Parent component to display, i.e., the title of this .svx file.
How can I assign my export let frontMatter
the data from svx.meta
using the #await
block syntax?
// SvxRenderer.svelte
<script lang="ts">
import { loadSvx } from '$lib/loadSvx';
import { fade } from 'svelte/transition';
import Spinner from '$lib/components/ui/polish/spinner/Spinner.svelte';
import ErrorRenderer from './ErrorRenderer.svelte';
export let slug: string;
export let frontMatter: any;
let spinnerHidden = false;
</script>
{#await loadSvx(slug)}
<div transition:fade on:outroend={() => (spinnerHidden = true)}>
<Spinner></Spinner>
</div>
{:then svx}
{#if spinnerHidden}
<div class="post-container" transition:fade>
<svelte:component this={svx.content} />
</div>
{/if}
{:catch error}
{#if spinnerHidden}
<div transition:fade>
<ErrorRenderer {error} />
</div>
{/if}
{/await}
I tried a silly workaround by adding {@const foo = () => (frontMatter = svx.meta )}
to the #then
block but that doesn't seem to work: if I then try to bind the frontMatter in the parent component, like so:
<script lang="ts">
import SvxRenderer from '$lib/components/svx/SvxRenderer.svelte';
import { page } from '$app/stores';
let frontMatter: any = null;
</script>
{#if frontMatter !== null}
<h1>{frontMatter.title}</h1>
{/if}
<SvxRenderer slug={$page.params.slug} bind:frontMatter />
The frontMatter stays null, and the title doesn't render.
(I realize I could do this by introducing an async function to onMount
and using #if
's to manually handle when my data is loaded instead, but I do feel like the #await
block syntax is more self-explanatory, so I'm wondering if there's a way to do this with #await
blocks.)
You could extend the promise chain in JS, something along the lines of:
$: promise = loadSvx(slug)
.then(result => {
frontMatter = result.meta;
return result;
});
{#await promise} ...
(Written as reactive in case slug
changes, though this still has a race condition that probably should be fixed.)