DEV Community

sarandha
sarandha

Posted on

Need help in SvelteKit query based tab navigation.

Trying to create tab based navigation in sveltekit which loads data from +page.server.js based on what tab is selected. the active tab is selected from the url query ?mode=tabname . Below is the snippet taken from a large project but I narrowed the issue down to this boilerplate code.

+page.svelte

<script>
    import { page } from "$app/stores";

    export let data;

    $: mode = $page.url.searchParams.get("mode");
</script>

<section>
    <nav>
        <a href="?mode=list">list</a>
        <a href="?mode=add">add</a>
    </nav>
    {#if mode == "list"}
        <table>
            <tr>
                <th>id</th>
                <th>name</th>
            </tr>
            {#each data.list as l (l.id)}
                <tr>
                    <td>{l.id}</td>
                    <td>{l.name}</td>
                </tr>
            {/each}
        </table>
    {:else if mode == "add"}
        <form action="">
            <input type="text" name="name" />
            <button type="submit">save</button>
        </form>
    {:else}
        <b>Select an option from above</b>
    {/if}
</section>
Enter fullscreen mode Exit fullscreen mode

+page.server.js

export const load = async ({ url }) => {
    // maybe needed in both tabs.
    const info = {
        appname: "demo",
    };
    // only needed in "list" tab.
    const list = [
        { id: 1, name: "test one" },
        { id: 2, name: "test two" },
        { id: 3, name: "test three" },
    ];

    // Previously, I was returning all the data
    // without detecting any tab.
    // There was no problem with it apart from
    // performance issues
    // return {
    //     info,
    //     list,
    // };

    // seperating the returned data based on tab name
    // that's when the issue arise
    const mode = url.searchParams.get("mode");
    if (mode == "list") {
        return {
            info,
            list,
        };
    } else if (mode == "add") {
        return {
            info,
        };
    }};
Enter fullscreen mode Exit fullscreen mode

After navigation from 'list' to 'add' tab, this error is thrown in chrome console:

chunk-ERBBMTET.js?v=7f9a88c7:2609 Uncaught (in promise) Error: {#each} only works with iterable values.
    at ensure_array_like_dev (chunk-ERBBMTET.js?v=7f9a88c7:2609:11)
    at Object.update [as p] (+page.svelte:18:29)
    at Object.update [as p] (+page.svelte:12:35)
    at update (chunk-ERBBMTET.js?v=7f9a88c7:1351:32)
    at flush (chunk-ERBBMTET.js?v=7f9a88c7:1317:9)
Enter fullscreen mode Exit fullscreen mode

Looks like it's complaining about data.list even after navigation to the tab which does not even need data.list. returning both info and list object for every tab solves the issue and also wrapping the #each block in #if block does the trick eg:

{#if data.list}
    {#each data.list as l (l.id)}
      <tr>
        <td>{l.id}</td>
        <td>{l.name}</td>
      </tr>
    {/each}
{/if}
Enter fullscreen mode Exit fullscreen mode

Given that I'm not very experienced in SvelteKit, I not sure what am I doing wrong. Any help is appriciated. Thanks

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now