I have a page (a dynamic route) where I am fetching data from an API in the load function. What is the correct way to show a loading indicator till the data is fetched. Things I have tried:
- Using await block. I return a promise to fetch function and then in the normal script tag, I export a promise variable. I then resolve this promise manually after manipulating the data.
<script context="module">
export async function load({ fetch, page }) {
let collectionId = page.params.id;
let endpoint = url;
const promise = fetch(endpoint);
return {props:{promise}};
}
</script>
then in normal script tag
<script>
export let promise = new Promise(() => '');
promise = new Promise((resolve, reject) => {
promise.then(function (response) {
if(response.ok){
console.log('response');
response.json().then(function (json) {
console.log('data in promise');
console.log(json);
let posts = json.map((post) => new Post(post));
posts = posts.sort(function (a, b) {
return a.id - b.id;
});
resolve(posts);
});
}else{
response.text().then((text)=>reject(text));
}
});
});
</script>
then in HTML
{#await promise}
<Shimmer items="3" />
{:then posts}
<Cards data={posts} />
{:catch error}
<Error message={error}/>
{/await}
This works fine the first time, I am guessing, this works when the page is rendered server side. But on subsequent calls, my promise resolution logic doesn't get called and I receive promise directly in my await block, where there is no logic to manipulate it.
- I export a variable to receive final processed data from the load function and in HTML, I try to display the loading indicator till this variable is undefined using {if} block. This works for the first time when the variable is actually undefined, but on subsequent calls, only the value of this variable changes but it is never undefined.
let posts;
{#if posts===undefined}
Loading...
{:else}
{posts}
{/if}