'Endless loop in react and socket.io
I'm trying to build a realtime chat message. In the client's side (React), whenever a new user enters the chat, the socket's event usuarios-conectados gets triggered (this socket event gives me an array of all the users connected at the time).
Then, I tried to set that array of users in a useState, but because of that, the component goes into a loop and keeps re-rendering itself.
That seems to be the problem because whenever i call useSocket, the console.log(users) keeps printing the connected users over and over
import { useEffect, useState } from 'react'
import { io } from "socket.io-client";
export const useSockets = () => {
const [socket, setSocket] = useState(
io('http://localhost:8080', {
'extraHeaders': {
'x-token': localStorage.getItem('x-token')
}
})
)
const [users, setUsers] = useState([])
useEffect(() => {
socket.on('connect', () => {
console.log('Sockets online')
})
socket.on('usuarios-conectados', (newUsers) => {
setUsers(newUsers);
console.log(users);
})
return () => {
socket.on('disconnect', () => {
console.log('Sockets offline')
})
socket.disconnect()
}
}, [])
return [users]
}
Solution 1:[1]
You should not store io in a state instead create a file and import in your component and then after you initialize the socket itself will listen to events that you define. let me show in code.
//src/utils/socket.js
import io from "socket.io-client"
export const socket = io(process.env.BACKURL);
// component.jsx
import {socket} from './utils/socket'
const [commentData , setCommentData] = useState([]);
useEffect(() => {
socket.on("connect_error", () => {
console.error("socket error!");
socket.close();
});
// websokcet to comments
socket.on("load_comment", (payload) => {
setCommentData(payload);
});
return () => {
socket.close();
}
}, [])
// second useEffect to see if statesChanged
useEffect(() => {
console.log('Changed' , commentData)
} , [commentData])
Solution 2:[2]
You should not store the IO in a state but call it in a context, for example, let me show in code.
- Create a context
import React from 'react';
import io from 'socket.io-client';
const SOCKET_ADDR = process.env.REACT_APP_SOCKET_ADDR || '<your server>';
export const socket = io(SOCKET_ADDR, { withCredentials: false, transports: ['websocket'] });
export const SocketContext = React.createContext();
- And add it wherever you want
import { SocketContext, socket } from './socket/SocketContext';
useEffect(() => {
socket.on('connect', () => {
socket.on('welcome', (res) => {
console.log(res);
});
});
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Paiman Rasoli |
| Solution 2 | Jean-Pierre Carvalho |
