'ReactJs Socket Client doesn't receive data from Flask Socket using emit(... , to=room)

I'm trying to develop a real-time chess app with Flask socket-io and ReactJs. My problem is that when setting emit(..., broadcast=True) on the server-side, the front-end works fine and React can receive the data. However, I want to implement private chess data transferring via emit(..., to=room). I set the room name to the host session ID via request.sid, however, nothing is transmitted as a result. Below is my code for the logic.

Thanks in advance

server.py

from flask import Flask, redirect, url_for, request, session
from flask_session import Session
from flask_socketio import SocketIO, send, emit, join_room, rooms
from config import ApplicationConfig
from flask_cors import CORS

app = Flask(__name__)
CORS(app)
app.config.from_object(ApplicationConfig)

socketio = SocketIO(app, cors_allowed_origins='*', async_mode="eventlet")
server_session = Session(app)

#Set-up logging to ERROR only
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)

#Change on deployment
app.host = 'localhost'
app.debug = True;
USERS={}
#------------------------- socket ----------------------------------------
@socketio.on('connect')
def connect(auth):
    pass
    # print("----------------------- | Connected | -----------------------------")
    # print(f"User Connected with ID: {request.sid}")
    # print("-------------------------------------------------------------")
@socketio.on('join')
def on_join(data):
    if data['room']!="host":
        join_room(USERS[data['room']]['sid'])
        print(f"{request.sid} has joined room {USERS[data['room']]['sid']}")
        send(f"Welcome to {request.sid}, {data['username']}", to=USERS[data['room']]['sid'])
    else:
        join_room(request.sid)
        print(f"{request.sid} has joined room {request.sid}")
        send( f"Welcome to {request.sid}, {data['username']}")

@socketio.on('connect-to-game')
def connect_to_game(payload):
    try:
        roomHost = payload['friendUsername']
        userName = payload['username']
        USERS[roomHost]["with"] = userName
        USERS[roomHost]["withSid"] = request.sid
        USERS[roomHost]["status"] = "in-game"

        # Create the player object
        USERS[userName] = {
            "host"   : USERS[roomHost]['sid'],
            "status" : "in-game",
            "sid"    : request.sid,
            "with"   : roomHost,
            "withSid": USERS[roomHost]["sid"],
        }
        if(USERS[roomHost]["side"] == "black"):
            USERS[userName]["side"] = "white"
        else:
            USERS[userName]["side"] = "black"

        # Sending data to the host 
        to_send = {
            "host"    : USERS[roomHost]['sid'],
            "status"  : "in-game",
            "sid"     : USERS[roomHost]["sid"],
            "with"    : userName,
            "withSid" : request.sid,
            "side"    : USERS[roomHost]["side"]
        }
        # join_room(roomHost)
        # print(f"{userName} has join room: {USERS[roomHost]['sid']}")
        print(f"{to_send}")
        # , room= to_send['host']
        emit("connect-user", to_send, to=USERS[roomHost]['sid'])
        return True
    except:
        return False


@socketio.on("create-user")
def onCreateUser(payload):
    USERS[payload['username']] = {
        "host"    : request.sid,
        "status" : "pending",
        "sid"    : request.sid,
        "with"   : "None",
        "withSid": "None",
        "side"   : payload['side']
    }
    # join_room(request.sid)
    # print(f"{payload['username']} has join room: {request.sid}")

    # session['username']= payload['username']

@socketio.on('disconnect')
def disconnect():
    pass


@socketio.on('message')
def handleMessage(msg):
    print('Message: ' + msg)
    send(msg, broadcast=True)
    return None

@socketio.on("chess-move")
def handleChessMove(chessMoveData):
    # room=USERS[chessMoveData['username']]['withSid']
    print(f"{request.sid} is Sending data via room: {chessMoveData['host']}")
    #, room=chessMoveData['host']
    emit("update-chess-move", chessMoveData['move'], to=chessMoveData['host'])

#------------------------- app routing ------------------------------------
@app.route('/favicon.ico')
def favicon():
    return redirect(url_for('static', filename='favicon.ico'))


@app.route('/api/user/<username>', methods=['GET'])
def get_user(username):
    return USERS[username], 200

@app.route('/api/users', methods=['GET'])
def get_users():
    return USERS, 200

if __name__ == "__main__":
    socketio.run(app, port=5000)

create_game.jsx

import {useState, useEffect} from "react"
import configData from "../config.json"
import Link from 'next/link'

import io from "socket.io-client"
let socket = io.connect(configData.SOCKET_URL)



function createGame(){
    const [username, setUsername] = useState("");
    const [friendUsername, setFriendUsername] = useState("");
    const [side, setSide] = useState("white")

    useEffect(()=>{
        // console.log(session);
    }, [])

    function connectToGame(){
        socket.emit('join', {username: username,room:friendUsername})

        socket.emit("connect-to-game", {
            username: username,
            friendUsername: friendUsername
        });

    }
    function createGame(){
        socket.emit("join", {username: username, room : "host"})
        socket.emit("create-user", {username: username, side: side});

    }

    return(
        <div>
            <label htmlFor="userName">Your preferred username: </label>
            <input 
                value={username} 
                type="text" 
                name="userName" 
                placeholder="Wonton Soup"
                onChange={e => {setUsername(e.target.value)}}
            />
            <br />
            <br />
            <label>
                <input  type="radio" 
                        checked={side==="white"}
                        onChange={() =>{setSide("white")}} 
                        name="side"/>
                White
            </label>
            <br />
            <label>
                <input  type="radio" 
                        checked={side==="black"}
                        onChange={() =>{setSide("black")}}
                        name="side"/>

                Black
            </label>
            <br />
            <br />
            <Link href={`/chess/${username}`}>
                <button onClick={createGame} > Create A Game </button>
            </Link>

            <br />
            <br />
            <br />
            <label htmlFor="friendName">Your friend already set up a game?? Join their game by their username</label>
            <br />
            <br />
            <input 
                value={friendUsername} 
                type="text" 
                name="friendName" 
                placeholder="Corn Soup"
                onChange={e => {setFriendUsername(e.target.value)}}
            />
            <Link href={`/chess/${username}`}>
                <button onClick={connectToGame} > Join Game </button>
            </Link>


        </div>
    )

}
export default createGame;

chess/[id].jsx

import {useState, useEffect} from "react"
import * as ChessJS from "chess.js";
import dynamic from 'next/dynamic';
import {useRouter} from 'next/router'
import configData from "../../config.json"
import axios from 'axios'

import io from "socket.io-client"
let socket = io.connect(configData.SOCKET_URL)

const Chessboard = dynamic(() => import('chessboardjsx'), {
  ssr: false
});

const Chessjs = typeof ChessJS === "function" ? ChessJS : ChessJS.Chess;
const game = new Chessjs();


function ChessGame(){
  //------------------------- Chess States -------------------------------
  const [fen, setFen] = useState("start");
  const [history, setHistory] = useState([]);
  const [currentSquare, setCurrentSquare] = useState("");
  const [currentPieceSquare, setCurrentPieceSquare] = useState("");
  
  //---------------------- Connection State  ----------------------------
  const [username, setUsername] = useState(useRouter().query.id);
  const [gameState, setGameState] = useState({});
  //-------------------- Chat States -------------------------------
  const [chatLogs, setChatLogs] = useState (["Welcome to Player 1 and 2 to Chess"]);
  const [message, setMessage] = useState("");
  //-------------- Initial Talk to Server ----------------------------

  useEffect(()=>{

    async function fetchUserData(){
      if(Object.keys(gameState).length === 0 && gameState.constructor === Object){
        let response = await fetch(`${configData.FLASK_URL}/user/${username}`);
        response = await response.json();
        setGameState(response)
      }
    }
    fetchUserData();
  }, [])

  useEffect(() =>{
   
    socket.on("connect-user", connectRequest=>{
      console.log("------------------------ connectRequest -----------------------");
      console.log(connectRequest);
      console.log("------------------------ --------------- -----------------------");

      setGameState(connectRequest);
    })

    socket.on("update-chess-move", chessData =>{
      let move = game.move({
        from : chessData.from,
        to: chessData.to,
        promotion: "q"
      })
      if(move !== null){
        setFen(game.fen());
        setHistory(game.history());
      }
    }) 
  }, [socket, game])

  useEffect(()=>{
    socket.open();
    
    socket.on("message", msg=>{
      setChatLogs([...chatLogs, msg]);
    })  

    // return( ()=>{
    //   socket.close();
    // })
  }, [socket,chatLogs.length])
    
  // UI Logic
  function changeTextBox(e){
    setMessage(e.target.value);
  }

  //When Send button is clicked
  function onSendClick(){
    //Send the message to the Flask Socket Server 
    if(message !== ""){
      socket.emit("message", message);
      setMessage("");
    } else{
      console.log("Bro Message can't be empty!!")
      console.log(document.cookie);
    }
  }
      
  // --------------------------- Chess Stuffs ---------------------------------------  

  function onDrop( {sourceSquare, targetSquare} ){
    // Pass in an object with sourceSquare and targetSquare 
    console.log(`on Drop: from ${sourceSquare} to ${targetSquare}`);
    let move = game.move({
        from : sourceSquare,
        to: targetSquare,
        promotion: "q"
    })
    if(move !== null){
        setFen(game.fen());
        setHistory(game.history());
        socket.emit("chess-move", {move: move, host : gameState.host});
    }
  }

  function onSquareClick(square){
      console.log("onSquareClick: " + square);
      console.log(fen);
      console.log(gameState);
  };

  function mouseOverSquare(square){
      console.log(square);
  }


  return(
      <div className="Chess">
        <h1>Welcome: {username} </h1>
        <h1>
          {gameState.status}
        </h1>
        <div id="ChessBoard">
          <Chessboard
              onDrop={onDrop}
              onSquareClick={onSquareClick}
              position={fen}
              mouseOverSquare={mouseOverSquare}
              orientation={gameState.side}
              />
            {history.map( move => <p key={move}>{move}</p>)}
          </div>

          <div id="ChatBox">
          {
            //Display chat logs
            chatLogs.length > 0 && chatLogs.map((msg, index) => { 
              return(
                <div className="chat-message" key={index}>
                <p>{msg}</p>
                </div>
            )})
          }
          </div>
          <input value={message} name="message" onChange={e => {changeTextBox(e)}}/>
          <button onClick={onSendClick}>Send Message</button>
      </div>
  )
}

export default ChessGame;


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source