Uncaught TypeError: Illegal invocation

オープン
#5,308 コメント 4 件 リアクション 1 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
nextjs, react, typescript
領域
backend, frontend

調査の方向性

提供された Next.js クライアントの再現コードで io() の呼び出しと connectMessageSocket エントリーポイントから始め、Socket インスタンスを Valtio プロキシでラップすると呼び出しエラーが発生するかどうかを切り分けます。token が最初は利用できない状態で認証済み接続のフローを再現し、token が提供されると正常に接続されることを確認します。

索引モデルが issue の本文から書いたものです。

説明

to triage

Describe the bug
It produces Uncaught TypeError: Illegal invocation error when calling io()

context: I'm working in a react project where valtio is used for state manamement.

To Reproduce

Socket.IO server version: 4.8.1

Server

Using Nest.js for server. The server is working fine.

Socket.IO client version: 4.8.1

Client

// (next.js projec) the valtio store
'use client';
import {proxy, ref} from "valtio";
import {devtools, useProxy} from "valtio/utils";
import {IS_PRODUCTION_MODE, isServer} from "@/util/constants";
import {io, Socket} from "socket.io-client";
import {endpoints} from "@/util/urls";

type MsgModule<Actions = any> = {
  socket: Socket;
  connecting: boolean;
  actions: Actions
}

type Data = {
  message: MsgModule;
}
export const socketStore = proxy<Data>({
  message: {
    socket: io(endpoints.api.baseUrl + '/message', {
      auth: {
        token: ''
      },
      autoConnect: false
    }),
    connecting: false,
    actions: ref({
      abc: () => {}
    }),
  },
});

// socketStore.message.

export const useStoreSockMsg = () => useProxy(socketStore.message);

devtools(socketStore, {
  name: 'socket',
  enabled: !isServer && !IS_PRODUCTION_MODE,
});

export const socketActions = {
  connectMessageSocket(accessToken: string) {
    if (socketStore.message.socket.connected || socketStore.message.connecting) return;

    console.log('proceed to socket connection with token', accessToken)

    socketStore.message.socket = io(
      endpoints.api.baseUrl + '/message',
      {
        auth: {
          token: accessToken,
        },
        autoConnect: false,
      }
    );

    // Listen for connection events
    socketStore.message.socket.on('connect', () => {
      console.log('socket is connected')
    });

    socketStore.message.socket.on('disconnect', () => {
      console.log('socket is disconnected')
    });

    // Handle auth errors (e.g., expired token)
    socketStore.message.socket.on('connect_error', async (err) => {
      console.log('socket connection err: ', err.message)

      // if (err.message === 'Unauthorized') {
      //   retry connection with updated token ...
      // }
    });


    socketStore.message.socket.connect();
  },

  // Disconnect and cleanup
  disconnectSocket: () => {
    if (socketStore.message.socket) {
      socketStore.message.socket.disconnect();
    }
  },

};
// the component
function MessageSocket() {
  const userStore = useStoreUser();
  const sockStore = useStoreSockMsg();

  useEffect(() => {
    if (sockStore.socket.connected || !userStore.at) return; // at is access token
    socketActions.connectMessageSocket(userStore.at); // calling this producting the err: Uncaught TypeError: Illegal invocation

    return () => socketActions.disconnectSocket();
  }, [userStore.at, sockStore.socket.connected]);

  useEffect(() => {
    console.log('sock connected?', sockStore.socket.connected)
  }, [sockStore.socket.connected]);

  // ...
}

Expected behavior
Obviously expectation was to successfully connect, The official docs has a guide on how to use with react but that doesn't covers how to use with authentication when the token becomes available later.

Platform:

  • Device: A Desktop PC
  • OS: Ubuntu 24.04
主要言語
TypeScript
スター
63.2k
フォーク
10.2k
平均マージ
6日 4時間
マージ済み PR(30日)
6

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

socketio/socket.io のほかの issue

socketio/socket.io の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。