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

Use reactive Variables Between Components in Svelte

I have a question regarding using reactive variables from component3 in my example in component 2. I have two checkboxes in component2 and I am having a reactive array that I want to use in component 2 but it does not quite work the way I want it to work. The repl can be found here: https://svelte.dev/repl/b8109591f22541949309be8404336afa?version=3.49.0

This is the main app

<script>
    import Component2 from './Component2.svelte';
    import Component3 from './Component3.svelte';
</script>


<Component3/>
<Component2/>

Component 2:

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

<script>
    import a2 from './Component3.svelte';
</script>

{#if a2[0]}
<p>
    Hi
</p>
{:else}
<p>
    Not Hi
</p>
{/if}

Component 3

<script>
 let initial_categories = [
        {name: 'SPINS', checked: true}, 
        {name: 'TRAIN', checked: true}
    ]
 let vec_names = [
        'SPINS', 'TRAIN'
    ]
 
    export let a2 = [];
    $: {
     a2 = [];
    for(let i = 0; i < initial_categories.length; i++) {
        let stringify = JSON.stringify(initial_categories[i]);
        stringify = JSON.parse(stringify)["checked"];
      a2 = a2.concat(stringify);
    }
    }
</script>

{#each initial_categories as { name, checked }}
    <label class="cats">
            <input type=checkbox bind:group={vec_names} bind:checked={checked} name="Category" value={name}>
            {name}
    </label>
{/each}

{a2}

>Solution :

This does not work:

<script>
    import a2 from './Component3.svelte';
</script>

a2 is simply the constructor of Component3 with a bad name.

You can only export variables that are not bound to component instances from the context="module" script, and those variables will not be reactive, so you need to use stores to preserve reactivity across components.

So something like this in #3:

<script context="module">
    import { writable } from 'svelte/store';
    export let a2 = writable([]);
</script>
<script>
    // ...
    $a2 = [];
    for(let i = 0; i < initial_categories.length; i++) {
        // ...
        $a2 = $a2.concat(stringify);
    }
</script>

And the import will be named instead of the default in #2:

<script>
    import { a2 } from './Component3.svelte';
</script>

{#if $a2[0]}
  <p>Hi</p>
{:else}
  <p>Not Hi</p>
{/if}

REPL


I would recommend defining a shared state higher in the hierarchy and passing it down to the components instead of doing the above. This can be done via props or via a context. With props the store does not need to used as long as the props are using bind: on the components that modify state.

E.g. in the main component:

<script>
    import Component2 from './Component2.svelte';
    import Component3 from './Component3.svelte';
    
    let state = [];
</script>


<Component3 bind:state />
<Component2 {state} />

Then just add export let state to the other two.

REPL

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