3

I want to rerender "Body" (my svelte component) whenever "view.current" changes so it renders the corresponding .svelte view/component:

App.svelte

    <script>
    import Header from "./components/Header.svelte";
    import Footer from "./components/Footer.svelte";
    import Body from "./components/Body.svelte";

    import Login from "./views/Login.svelte";
    import Dashboard from "./views/Dashboard.svelte";

    import { view } from "./store";
</script>

<Header />
    <Body>
        {#if view.current === view.login}
            <Login />
        {:else if view.current === view.dashboard}
            <Dashboard />
        {/if}
    </Body>
<Footer />

In "Body.svelte" i just have a slot that gets styled

Body.svelte

    <div class="container">
    <div class="content">
        <slot></slot>
    </div>
</div>

<style>
    .container {
        padding: 1em;
        display: flex;
    }
    .content {
        margin: auto;
    }
</style>

In Login.svelte (and other svelte components) i want to change "view.current":

Login.svelte

<script>
    import { view } from "../store";

    function handleLoginClick() {
        view.current = view.dashboard;
    }
</script>


<button type="button" on:click={handleLoginClick} class="btn btn-primary btn-lg login-btn">Login</button>

<style>
    .login-btn {
        display: block;
        margin: auto;
    }
</style>

store.js

    const user = {
    username: "",
    fullname: "",
    role: null,
    isLoggedIn: false
};

const view = {
    login: 1,
    dashboard: 2,
    current: 1
};

export {
    user,
    view
}

The value of "view.current" changes as expected, however "Body" does not update/rerender. So it always shows the login.svelte no matter to what "view.current" has been set. Is there a quick and easy way to make "Body" reactive to "view.current" so that it rerenders so that the if/else-block in "App.svelte" get's reevaluated?

6
  • Why do you want your Body component to re-render?
    – Tholle
    Commented Oct 26, 2020 at 9:18
  • When view.current is set to lets say "login" i want to render the stuff in login.svelte, when it is set to "dashboard" i want to render "dashboard.svelte" and so on.
    – Horst
    Commented Oct 26, 2020 at 9:23
  • is this view a svelte store ? Commented Oct 26, 2020 at 9:31
  • No, it's just a js file. I also tried to make "view" to a svelte.store, but it behaves the same way. I have edited the post and added the contents of store.js.
    – Horst
    Commented Oct 26, 2020 at 9:34
  • Try $: currentView = view.current; and use currentView in the markup? Note: I might be completely wrong, I'm not yet 100% comfortable with Svelte.
    – sp00m
    Commented Oct 26, 2020 at 9:37

1 Answer 1

8

Importing a regular variable like that in a component creates a local copy of said variable. The view you are referring to in the Login is not shared with the one in App, so the changes are not reflected there.

The "Svelte-way" of sharing state like that accross components is to use a store.

In your setup that would mean you define view as a store first:

import { writable } from 'svelte/store'

const view = writable({
    login: 1,
    dashboard: 2,
    current: 1
});

In the components themselves you have to prefix the store with $

<script>
    function handleLoginClick() {
        $view.current = $view.dashboard;
    }
</script>
{#if $view.current === $view.login}
    <Login />
{:else if $view.current === $view.dashboard}
    <Dashboard />
{/if}
1
  • Thank you, this does the trick. Did not know it creates a local copy of it.
    – Horst
    Commented Oct 26, 2020 at 9:49

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.