Search code examples
javascriptarraysstoresvelte

In a Svelte readable store array, How can I update only one item without touching the others?


I guess this question is more on JS sysntax, but I have a store array like this:

export const store = readable( {id: 0, value: 0} , set => {
    let socket = new WebSocket("ws://localhost:65432");
    socket.onmessage = function (event) {
        var data = JSON.parse(event.data);
        set({id: 0, value: data});
    }
})

The store defines its set method to update the value from a websockets connection. How can I do the same but with a store array? Something like:

arr = [];
for(i=0; i<numberOfItems; i++) {
    arr = [...arr,{id: i, value: 0}];
}

export const store = readable( [{arr}] , set => {
    let socket = new WebSocket("ws://localhost:65432");
    socket.onmessage = function (event) {
        var data = JSON.parse(event.data);
        var channel = data.channel;
        set({id: data.channel, value: data.value});
    }
})

Here is where I dont manage to "set" o the array, and without having to declare the whole array every update.


Solution

  • I think in your case what you want to save in the store is not an array, but an object, it would make easier this step. Something like:

    export const store = readable({} , set => {
        let channels = {};
        let socket = new WebSocket("ws://localhost:65432");
        socket.onmessage = function ({data}) {
            let { channel, value } = JSON.parse(data);
    
            // update `channels`
            channels = {...channels, [channel]: value };
    
            // set the new `channels` as store value
            set(channels)
        }
    })
    

    Notice that in this way you will have directly the channel as key of the object: so if a channel already exists, it will be updated instead of added. And if it doesn't exists, it will be added.

    In your subscriber you can therefore have something like:

    store.subscribe(channels => {
      for (let [channel, value] of Object.entries(channels)) {
        console.log(`channel ${channel} received ${value}`);
      }
    });
    

    As final note, consider that this code creates a new object every update to avoid side effect, that's common practice. However, if you have a lot of data in the object and you're aware of the possible implication, you could just add / update the single key without duplicating the object every time, for performance / memory reason.

    Hope it helps!