Home > Blockchain >  Issue using Socket.io with Pinia
Issue using Socket.io with Pinia

Time:05-23

I'm trying to use Pinia to manage some global state in a Vue.js app I'm building, specifically I want to share a Socket.io instance between various components and views. However I'm getting a

this.socketObject.emit is not a function

error when calling functions from the Socket.io instance, when I call them from a component other than the component/view the Socket.io instance was created in. Here's some excerpts of the code.

@/views/LobbyView.vue (This is where I create the Socket.io instance and pass it to the Pinia store, I can use emit fine in this file without any errors)

import io from "socket.io-client";
import { useSocket} from "@/store/index";
    ...     
setup() {
   const socketObject = useSocket();
   return { socketObject};
},
    ...
async mounted() {
   this.socketObject = await io("http://localhost:8000");
   this.socketObject.emit("createNewRoom");
}

@/store/index.js Pinia store

import { defineStore } from "pinia";
...
export const useSocket = defineStore({
  id: "socket",
  state: () => {
    return {socketObject: Object};
  },
  getters: {},
  actions: {},
});

@/components/lobbySettings (this is the file where I have issues using Socket.io in via my Pinia store)

import { useSocket } from "@/store/index";
...
  setup() {
    const socketObject = useSocket();
    return { socketObject};
  },

...
  methods: {
    startGame() {
        this.socketObject.emit("updateRoom", this.roomInfo);
    },
  },

When the start game method is called on a button press, if I catch the error I get

this.socketObject.emit is not a function

I don't quite understand why Pinia isn't giving me access to functions from my Socket.io instance, the store seems to be working fine for other data in my app, just cant call these functions.

CodePudding user response:

useSocket returns a store, not socket instance. It should be used as:

const socketStore = useSocket();
...
socketStore.socketObject.emit(...)

io(...) doesn't return a promise, it's semantically incorrect to use it with await.

The use of Object constructor is incorrect. If a value is uninitialized, it can be null:

  state: () => {
    return {socketObject: null};
  },

The mutation of store state outside the store is a bad practice. All state modifications should be performed by actions, this way they can be easily tracked through devtools, this is one of benefits of using a store.

At this point there's no benefit from packing socketObject inside a store. Socket instance could be either used separately from a store, or socket instance could be abstracted away and made reactive with store actions, etc.

  • Related