I have a svelte component that can be toggled on or off and that fetches some async data. This async call is slow so I want to avoid making it, and only want to make the call when the component is visible (toggled on).
I want to know if there is a way to render this component once, then re-render only if the async call changes and not when toggling on or off? I almost want to "cache" the component.
I have tried two approaches that both work but have downsides.
See this REPL for full working example of both approaches: https://svelte.dev/repl/397fdf11988c4d4fbb98d375adfc8539?version=3
Both of these approaches use this component to display the result:
<!-- DisplayResult.svelte -->
<script lang="ts">
export let getResultFn;
$: colorPromise = getResultFn();
</script>
{#await colorPromise}
Loading...
{:then color}
The color is {color}
{/await}
Approach 1: Render component then hide
The first is to always render the component and then hide it when not active. The downside to this is that when the async call changes, it is immediately called which is expensive. I would rather only make this call initially when the component is visible (the toggle is used many times so I only want to get new data for open toggles). Furthermore, I cant use transitions here since the component is never re-rendered
<!-- Item.svelte -->
<button on:click={() => { active = !active;}} >
Toggle
</button>
<div
transition:slide
class:hidden={!active}
>
<DisplayResult getResultFn={() => getResults(idx)} />
</div>
<style>
.hidden {
display: none;
}
</style>
Approach 2: Conditionally toggle
The other option is to create the component when visible, then destory when hidden. The good part is this only gets the data when the component is visible but then it makes extra calls every time the component is subsequently toggled. I can also use transitions here which is nice
<!-- Item.svelte -->
<button on:click={() => { active = !active;}} >
Toggle
</button>
{#if active}
<div transition:slide >
<DisplayResult getResultFn={() => getResults(idx)} />
</div>
{/if}
Best of both?
Is there a way to get the best of both worlds and
- Only get data initially when component is actually visible so can lazily fetch (like Approach 2)
- But then cache call and do not re-render every time (like Approach 1)