Reputation: 990
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
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