Search code examples
typescriptsveltesveltekit

SvelteKit navigation delayed by await


I have a component that loads some data asynchronously and displays it. There are also ways to navigate to different pages from that component. However, the navigation only happens after all #await requests are resolved. I'd like to navigate immediately after the user clicks on the link and not wait for all the data of the old page to load. Is there a way to do that?

Rough outline of what I'm doing:

<script lang="ts">
  import { goto } from '$app/navigation';

  let slowRequest = getSlowData();
</script>

<div class="flex flex-col">
  {#await slowRequest}
    Loading...
  {:then result}
    result
  {/await}
  <button onclick={() => goto("/some/other/page")}>
    Navigate
  </button>
</div>

When I click the button I have to wait for the request to resolve before I'm redirected. Is there any way to directly go to the new page without waiting for a response?


Solution

  • You should be using onMount func to fetch data. Do not directly use await outside of script tags. This way your UI won't be blocked and you can navigate without waiting for fetchData() to complete.

    import { onMount } from 'svelte';
    
    let slowRequest;
    
    onMount(() => {
        fetchData();
    });
    
    async function fetchData(categoryId?: string) {
        slowRequest = await getSlowData(val);
    }
    

    UPDATE: ANSWER TO THE QUESTION IN THE COMMENTS SECTION.

    If I understand you correctly, you want to fetch this data based on another variable that you choose from select-option html tag, if this is what you meant then try the following,

    // Inside the script tag
    function onChange(e) {
        const selectedCategoryId = e.target.value;
        fetchData(selectedCategoryId);
    }
    
    // Put this after the end of script tag.
    <select on:change={onChange}>
        <option value={undefined}>Select an item</option>
        <option value="id_1">Category 1</option>
        <option value="id_2">Category 2</option>
        <option value="id_3"> Category 3</option>
    </select>
    

    Note that I have modified the fetchData(categoryId?: string) function to accept an optional variable so that getSlowData(categoryId?: string) {...} API can be called with or without a value. i.e if categoryId is present then fetch the category specific data otherwise just load random data.