[Vuejs]-Html doesn't update consistently on ref value change in vue

1👍

I think your problem is because Vue’s reactivity system can have trouble tracking changes in certain situations, such as when directly modifying an object’s properties. To ensure consistent updates, we can use a ref to wrap the WebSocket object itself, and then access the readyState from within a computed property.

What I have modified in your code is the following:

  1. We use computed to create a reactive property wsState that reads the value of ws.wsState.value. This ensures that Vue will properly track changes to wsState.
  2. We initialize wsState with WebSocket.CONNECTING, so it has a value from the start.
<script setup>
import { ref, computed } from 'vue';

class Ws {
  ws; // WebSocket
  wsState = ref(WebSocket.CONNECTING); // Initialize with CONNECTING state

  constructor() {
    this.doConnect();
  }

  doConnect() {
    const ws = new WebSocket('wss://ws.ifelse.io/');
    this.ws = ws;
    
    ws.onopen = () => this.updateWsState();
    ws.onclose = () => this.updateWsState();
    ws.onerror = (e) => console.error(`ws err:`, e);
  }

  updateWsState() {
    this.wsState.value = this.ws.readyState;
    console.log(`ws state ${this.wsState.value}`);
  }

  toggleConnect() {
    if (this.ws.readyState === WebSocket.CLOSED || this.ws.readyState === WebSocket.CLOSING) {
      this.doConnect();
    } else {
      this.ws.close();
    }
  }
}

const ws = new Ws();
const wsState = computed(() => ws.wsState.value);
</script>

<template>
  <ul>
    <li>0 CONNECTING</li>
    <li>1 OPEN</li>
    <li>2 CLOSING</li>
    <li>3 CLOSED</li>
  </ul>
  <p>ws state: {{ wsState }}</p>
  <button @click="ws.toggleConnect">toggle connect</button>
</template>

If you have any further issues or questions, please let me know.

1👍

Thanks @Julian Buxton for the improvement. I find the problem of my code is this.wsState = ref(ws.readyState); in doConnect(). wsState gets binded to a different ref every time doConnect() is called. It should be binded only once in the constructor.

That line this.wsState = ref(ws.readyState); should be moved to the constructor:

// ...
class Ws{
  // ...
  constructor() {
    this.doConnect();
    this.wsState = ref(ws.readyState);
  }
  doConnect() {
    const ws = new WebSocket('wss://ws.ifelse.io/');
    this.ws = ws;
    ws.onopen = () => this.updateWsState();
    ws.onclose = () => this.updateWsState();
    ws.onerror = (e) => console.error(`ws err:`, e);
  }
  // ...
}
// ...
👤Jackoo

Leave a comment