Error 'Typeerror: Cannot read Property 'room' of Undefined'

Asked

Viewed 24 times

0

I’m developing a real-time chat application, using Reactjs on the front end and Node.js on the back end. I configured the Node server with Socket.io for the application. When entering the chat page itself, and trying to send a message it must connect to the server in question. However, when trying to connect the terminal returns the error:

C: Users*****\chat-app server index.js:30
socket.Join(user.room);
^
Typeerror: Cannot read Property 'room' of Undefined At socket. (C: Users Icaro Projetos chat-app server index.js:30:26)
At Socket.Emit (Vents.js:375:28)
At socket.emitUntyped (C: Users Icaro Projects chat-app server node_modules socket.io dist typed-Events.js:69:22)
AT: Users Icaro Projetos chat-app server node_modules socket.io dist socket.js:428:39
at processTicksAndRejections (Internal/process/task_queues.js:77:11)
[nodemon] app Crashed - Waiting for file changes before Starting...

I’m using

  • Express v4.17.1
  • Nodemon v2.0.12
  • Socket.io v4.1.3

Filing cabinet Index.js Server Side

const http = require('http');
const express = require('express');
const socketio = require('socket.io');
const cors = require('cors');

const { addUser, removeUser, getUser, getUsersInRoom } = require('./users');

const router = require('./router');

const app = express();
const server = http.createServer(app);
const io = socketio(server, {
    cors: {
        origin: "*",
        methods: ["GET", "POST"],
        allowedHeaders: ["my-custom-header"],
        credentials: true,
    }
});

app.use(cors());
app.use(router);

io.on('connect', (socket) => {
    socket.on('join', ({ name, room }, callback) => {
        const { error, user } = addUser({ id: socket.id, name, room });

        if(error) return callback(error);

        socket.join(user.room);

        socket.emit('message', { user: 'admin', text: `${user.name}, bem-vido à sala ${user.room}!`});
        socket.broadcast.to(user.room).emit('message', { user: 'admin', text: `${user.name} entrou no chat!` });

        io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room) });

        callback();
    });

    socket.on('sendMessage', (message, callback) => {
        const user = getUser(socket.id);

        io.to(user.room).emit('message', { user: user.name, text: message });

        callback();
    });

    socket.on('disconnect', () => {
        const user = removeUser(socket.id);

        if(user) {
        io.to(user.room).emit('message', { user: 'Admin', text: `${user.name} has left.` });
        io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room)});
        }
    });
});

server.listen(process.env.PORT || 5000, () => console.log(`Servidor rodando na porta 5000.`));

Filing cabinet Users.js Server Side

const users = [];

const addUser = ({ id, name, room }) => {
  name = name.trim().toLowerCase();
  room = room.trim().toLowerCase();

  const existingUser = users.find((user) => user.room === room && user.name === name);

  if(!name || !room) return { error: 'Nome de Usuário e Sala são obrigatórios!' };
  if(existingUser) return { error: 'Nome de Usuário já existe!.' };

  const user = { id, name, room };

  users.push(user);

  return user;
}

const removeUser = (id) => {
  const index = users.findIndex((user) => user.id === id);

  if(index !== -1) return users.splice(index, 1)[0];
}

const getUser = (id) => users.find((user) => user.id === id);

const getUsersInRoom = (room) => users.filter((user) => user.room === room);

module.exports = { addUser, removeUser, getUser, getUsersInRoom };

Filing cabinet Chat.js Client Side

import React, { useState, useEffect } from 'react';
import queryString from 'query-string';
import io from 'socket.io-client';

import './Chat.css';

import Input from '../Input/Input';
import InfoBar from '../InfoBar/InfoBar';
let socket;

const Chat = ({ location }) => {
    const [name, setName] = useState('');
    const [room, setRoom] = useState('');
    const [message, setMessage] = useState('');
    const [messages, setMessages] = useState([]);
    const ENDPOINT = 'localhost:5000';

    useEffect(() => {
        const { name, room } = queryString.parse(location.search);

        socket = io(ENDPOINT);
        
        setName(name);
        setRoom(room);

        socket.emit('join', { name, room }, () => {

        });

        return () => {
            socket.emit('disconect');

            socket.off();
        }
    }, [ENDPOINT, location.search]);

    useEffect(() => {
        socket.on('message', (message) => {
            setMessages([...messages, message]);
        });
    }, [messages]);

    // função para enviar mensagens
    const sendMessage = (event) => {
        event.preventDefault();

        if(message) {
            socket.emit('sendMessage', message, () => setMessage(''));
        }
    }

    console.log(message, messages);

    return (
        <div className="outerContainer">
            <div className="container">
                <InfoBar room={room} />

                <Input message={message} setMessage={setMessage} sendMessage={sendMessage} />
            </div>
        </div>
    );
}

export default Chat;

I’ve tried several ways to fix this, spent hours analyzing the code and nothing works.

1 answer

0

You are deconstructing the return object of the adduser function as if it is always returning something like this

{
  error: 'string',
  user: {},
}

But in the end the return of the function is object of user and not {user: {}} as expected.

The function addUser would look like this:

const addUser = ({ id, name, room }) => {
  name = name.trim().toLowerCase();
  room = room.trim().toLowerCase();

  const existingUser = users.find((user) => user.room === room && user.name === name);

  if(!name || !room) return { error: 'Nome de Usuário e Sala são obrigatórios!' };
  if(existingUser) return { error: 'Nome de Usuário já existe!.' };

  const user = { id, name, room };

  users.push(user);

  return {user};
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.