Deno fresh - List in island not updating

277 Views Asked by At

I'm creating a websocket based chat app to experiment with Fresh, but I'm struggling to render a basic list of messages to the page. Here's some code:

routes/chat.tsx

export default function Chat() {
    return (
        <div>
            // ...
            <MyIsland username={username.value}></MyIsland>
        </div>
    )
}

islands/MyIsland.tsx

export default function MyIsland(props: IslandProps) {

    const ws = useSignal<WebSocket | null>(null);
    const messageList = useSignal<Message[]>([]);

    useEffect(() => {
        if (props.username) {
            ws.value = new WebSocket("ws://localhost:5000?username=" + props.username);
            ws.value.onopen    = ()  => { console.log('Connected..') }
            ws.value.onmessage = updateMessages;
        }
    }, []);

    const updateMessages = useCallback((m: MessageEvent<string>) => {
        const data: WsData = JSON.parse(m.data);
    
        if (data.type == SocketMessageType.Text){
            const message: Message = data.value;
            messageList.value.push(message);
        }
    }, [])

    const send = useCallback((text: string) => {
        if (ws.value) {
            const data = // ...
            ws.value.send(JSON.stringify(data));
        }
    }, [ws]);

    return (
        <div>
            <Button onClick={() => send('test')}>Send</Button>
            <div>
                {messageList.value.map((m) => ( <MessageItem {...m} /> ))} // problem here
            </div>
        </div>
    )
}

I would expect the messageList.value.map at the bottom of MyIsland to be updated on the page as the list fills with messages, but this is not the case. I have verified that the list is being updated correctly in the background, it's just the html that is not updated. I'm very new to fresh and server+client rendered frameworks in general so I suspect I might be misunderstanding the way the islands are rendered. Thanks for any help!

1

There are 1 best solutions below

0
On BEST ANSWER

Your state isn't getting updated because your array reference doesn't change. You need to assign a new array to messageList.value in order to make it update the state.

Instead of

messageList.value.push(message);

do

messageList.value = [...messageList.value, message];

And it will work as you expect it.