Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Svelte components does not react to variable changes

I have a variable on a component and a function to change the value of that variable is exported from the component; that function is imported in another component to change the variable when it is triggered. The opened class should be added to the h1 element in the component.

Component.svelte

<script context="module">
    let active = false;
    
    export function ToggleColor() {
        active = !active;
        console.log(active)
    }
</script>

<h1 id="color" class:opened={active}>Hello</h1>

<style>
    #color {
        color: red
    }
    #color.opened {
        color: blue !important;
    }
</style>

The value of the variable is changed and logged in the console but the component (specifically adding and removing classes) does not react to it.

App.svelte

<script>
    import Component, {ToggleColor} from "./Component.svelte";
</script>

<Component />

<div on:click={ToggleColor}> click to change color </div>

Can a kind person tell me what I am getting wrong here, please. I have also created a REPL for this issue. Any incoming assistance is greatly appreaciated. Thanks in advance. Disclaimer: I am extremely inexperienced at Svelte.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem is that you are using the context="module" script:

A <script> tag with a context="module" attribute runs once when the module first evaluates, rather than for each component instance.
Variables defined in module scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a store.

Docs

Since there is only one instance of everything in the module script, you also would not be able to use multiple instances of the component: They all would share the same active value.

You could fix the code by properly using the instance script, though this requires that you use bind:this on the component to get a reference to the component instance:

<!-- In component -->
<script>
    let active = false;
    export function toggleColor() { active = !active; }
</script>
<!-- Usage -->
<script>
    import Component from "./Component.svelte";
    let component;
</script>

<Component bind:this={component} />
<button on:click={() => component.toggleColor()}>
    Click to change color
</button>

REPL

This is not how you would usually do this, though. Instead, just expose the active value as a prop and update it from the outside:

<!-- In component -->
<script>
    export let active = false;
</script>
<!-- Usage -->
<script>
    import Component from "./Component.svelte";
    let active = false;
</script>

<Component {active} />
<button on:click={() => active = !active}>
    Click to change color
</button>

REPL

(By the way, you should not add click handlers to arbitrary elements, but use a <button> instead. This way it will be more accessible and e.g. trigger on enter when focused.)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading