svelte-3svelte-store

Svelte array of springs


Using svelte motion I need to create an array of springs for various objects.

import { spring, type Spring } from 'svelte/motion';
.
.
.

let coords: Array<Spring<{ x: number; y: number }>> = [];
    for (let i = 0; i < foo.length; i++) {
        coords.push(
            spring(
                { x: 50, y: 0 },
                {
                    stiffness: 0.1,
                    damping: 0.1
                }
            )
        );
    }

Now when I use it in inline style

<img alt="eggs" src="./spam" 
style="transform: translate({$coords[j].x}px,{$coords[j].y}px)"
/>

I get the following error-

'coords' is not a store with a 'subscribe' method
Error: 'coords' is not a store with a 'subscribe' method
No overload matches this call.
   Overload 1 of 2, '(store:SvelteStore<any>):any' gave the following error.
      Argument of type 'Spring<{x:number; y:number;}>[]' is not assignable to the parameter of type 'SvelteStore<any>'.
      Property 'subscribe' is missing in type 'Spring<{x:number; y:number;}>[]' but is required in type 'SvelteStore<any>'.     
    Overload 2 of 2, '(store:SvelteStore<any> | null |undefined ):any' gave the following error.
       Argument of type 'Spring<{x:number; y:number;}>[]' is not assignable to the parameter of type 'SvelteStore<any>'.

How do I solve this without creating a custom store.


Solution

  • A $storeVar variable will only work for a store declared in a top-level variable. If you only need access to one of those stores, you could have a line like this in your <script>:

    $: myCoords = coords[j];
    

    and then $myCoords.x and $myCoords.y will work as you'd expect.

    If you need to subscribe to every store in an array, you'll need to manage the subscriptions yourself. It's not hard, but you'll need to ensure every subscription gets unsubscribed at the appropriate time.

    import { onDestroy } from "svelte";
    let storeValues = [];
    for ( let [i, store] of coords.entries() ) {
        let unsubscribe = store.subscribe( (value) => {
            storeValues[i] = value; // Svelte makes this reactive
        } );
        onDestroy( unsubscribe );
    }