greymatter
greymatter

Reputation: 990

Svelte store not updating on screen

I'm new to Svelte, and I'm making a rookie mistake. I have a websocket connection to a server, and I am logging hundreds of messages and adding them to a store, but the page does not update at all.

App.svelte

<script>
    import Socket from "./Socket.svelte"
    import msgs from './stores'
</script>

<main>
    <Socket items="{$msgs}"/>
</main>

Socket.svelte

<script>
    export let items
</script>

{items.length}
{#if items}
    {#each items as msg, i}
        <p>{i} {msg}</p>
    {/each}
{:else}
    <p class="loading">waiting...</p>
{/if}

socket.js

import { readable, writable } from 'svelte/store';

let msgs = []
const msgStore = readable(msgs)
export default msgStore

const socket = new WebSocket("ws://localhost:8080/socket");

socket.binaryType = "arraybuffer";

socket.onopen = function (event) {
  msgs = [...msgs, "Connected"];
};

socket.onmessage = function (event) {
  msgs = [...msgs, event];
  console.log(msgs.length)

  const msg = JSON.parse(event.data)
  const msgType = msg.messageType
  console.log(msgType)
};

In the browser, I get the 0 for the initial length of the items array, but it never updates, even though messages are flowing.

Upvotes: 3

Views: 4330

Answers (1)

rixo
rixo

Reputation: 25001

You're never actually pushing anything into the msgStore, just the msgs arrays... Which is not reactive per se.

Simplest in your case is to use a writable store:

const msgs = []
export const msgStore = writable([])

socket.onmessage(e => {
  ...
  msgs.push(msg)
  msgStore.set(msgs)
})

You can protect against external tempering by exporting a derived of this instead of the writable store:

export const publicMsgStore = derived(msgStore, x => x)

Or, to do it in one step with a readable store, you need it to wrap your whole logic:

export const msgStore = readable([], set => {
  const msgs = []
  ...
  socket.onmessage(e => {
    ...
    msgs.push(msg)
    set(msgs) // <= UPDATE THE STORE!!
  })
})

You need the call the injected set function to change the value of a readable store (or notify it that its value has changed).

Upvotes: 5

Related Questions