Jon49
Jon49

Reputation: 4606

Hide Routes in Svelte-Routing when logged out

When I try to hide the pages of certain routes when the user is not logged in it works well. But once the user is logged in the pages no longer show the content when I navigate to the page with svelte-routing's navigate method. But once I click on the route they are rendered fine. Am I doing something wrong? Below is the basic set up. You can also find it on github.

App.svelte

You can see in the example below that I hide the Routes in the if-else clause under the main HTML tag. When I'm on page /somewhere and am also already logged out and then click login and then click submit it is supposed to take me back to /somewhere which is does. But the text Somewhere doesn't show like it should until I click the link Somewhere. The expected result would be that it shows up.

<script>
import { Router, Link, Route, navigate } from "svelte-routing"
import Login from "./Login.svelte"
import Somewhere from "./Somewhere.svelte"
import Home from "./Home.svelte"

let user = null
var previousPath

$: user

function logout() {
    localStorage.clear()
    user = null
    navigate("/")
}

function loggedIn (event) {
    if (event) {
        user = { name: "George" }
        navigate(previousPath, { replace: true })
    }
}

function loggingIn() {
    previousPath = window.location.pathname
}

</script>

<Router>
    <h1>Test Login</h1>
    <nav>
        <Link to="/">Home</Link>
        {#if user === null}
        <Link to="/login" on:click={loggingIn}>Login</Link>
        {:else}
        <Link to="/somewhere">Somewhere</Link>
        <form on:submit={logout}>
            <input type="submit" value="Logout" />
        </form>
        {/if}
    </nav>
    <main>
        {#if user !== null}
        <Route path="/somewhere"><Somewhere /></Route>
        <Route path="/"><Home /></Route>
        {:else}
        <p>Please login</p>
        <Route path="/login"><Login on:loggedIn={loggedIn} /></Route>
        {/if}
    </main>
</Router>

Here's the other pages:


Home.svelte

<p>Yellow!</p>

Login.svelte

<script>
import { createEventDispatcher } from "svelte";

const dispatch = createEventDispatcher()

function submit() {
    dispatch("loggedIn", true)
}
</script>

<form on:submit={submit}>
    <input type="submit" value="Submit" />
</form>

Somewhere.svelte

<p>Somewhere!</p>

Upvotes: 3

Views: 1837

Answers (1)

Dawid Loranc
Dawid Loranc

Reputation: 892

After some investigation, I discovered that you could use the tick function as below:

import { tick } from "svelte"

...

async function loggedIn (event) {
    if (event) {
        user = { name: "George" }
        await tick()
        navigate(previousPath, { replace: true })
    }
}

And it works, but it looks ugly. I'm not sure if there is a better and cleaner way to do it, so you have to stick with it.

The tick is a function that resolves once any pending state changes have been applied. In your case, when the user is modified, it makes sure that the content of {:else} block is showed (although empty), and then navigates to the previous path, which causes mounting of components in Route.

Upvotes: 3

Related Questions