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.
>Solution :
The problem is that you are using the context="module" script:
A
<script>tag with acontext="module"attribute runs once when the module first evaluates, rather than for each component instance.
Variables defined inmodulescripts 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.
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>
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>
(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.)