2
votes

I am trying to create a navigation bar with sveltekit. So far, I have all the links (hash routes) working to be styled when clicked. However, after clicking the "Home" route several times, it stops causing the page to load, which causes my $page subscription to not update and thus style the link correctly.

My subscription that logs the current hash route: $: console.log($page.url.hash);

My test for styling the link: class:active={$page.url.hash === x.path.slice(1)

Even after the Home link stops being styled, all the other links will still be styled when clicked. I do get an empty string in the console on the first page load, and again after clicking away from Home and back on it. The second time clicking the Home link does not produce anything in the console.

The route changes in the address bar each time I click any link.

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

    const navItems = [
        {
            label: 'home',
            path: '/'
        },
        {
            label: 'how it works',
            path: '/#how-it-works'
        },
        {
            label: 'pricing',
            path: '/#pricing'
        },
        {
            label: 'partners',
            path: '/#partners'
        },
        {
            label: 'contact',
            path: '/#contact-us'
        }
    ];

    $: console.log($page.url);
</script>

<nav>
    {#each navItems as x}
        <a
            href={x.path}
            class="capitalize"
            class:active={$page.url.hash === x.path.slice(1)}
        >
            {x.label}
        </a>
    {/each}
</nav>

<style>
    .active {
        font-weight: bold;
        position: relative;
    }

    .active::after {
        content: '';
        width: 100%;
        height: 3px;
        position: absolute;
        left: 0;
        bottom: -8px;
        background-color: #17a398;
        border-radius: 999px;
    }
</style>
1
Could you create a REPL (svelte.dev/repl) to illustrate the problem?Coo
@Coo Could not get access to $app.stores from the REPL (expected), so I added a code snippet to the question. I ended up just putting /# onto the home route to force a re-render. It works; and with an appropriate test, applies the styles correctly.Kevin Williams

1 Answers

1
votes

I honestly think there might be a bug here, and you should definitely report it.

However, there is a workaround, you can use the goto function to navigate. This does seem to work.

Add the following import:

import { goto } from '$app/navigation';

Then in your navs update the code to this:

<nav>
    {#each navItems as x}
        <a
            on:click|preventDefault={() => goto(x.path)}
            href={x.path}
            class="capitalize"
            class:active={$page.url.hash === x.path.slice(1)}
        >
            {x.label}
        </a>
    {/each}
</nav>

Here, we prevent the default action of clicking the link, and instead we run the goto function (which is the programmatic equivalent of clicking a link).

In the brief testing I've done, the styles are updated correctly and the logs are shown as expected.