Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

368
Vistas
Socket.io y React: ¿La forma correcta también de recibir datos del servidor y establecer el estado en un componente?

Tratando de poner en marcha una aplicación de chat básica y teniendo problemas con repeticiones excesivas cuando se envía un mensaje. Aquí está el código aplicable para el cliente:

 const [chatMessages, setChatMessages] = useState([]); const sendChat = (e) => { socket.emit("sendMessage", e.target.elements.message.value); } useEffect(() => { socket.on("receiveMessage", (chatMessage) => { setChatMessages([...chatMessages, chatMessage]); console.log(chatMessages); }); }, [chatMessages]); return ( {chatMessages.map((message) => <p>{message}</p>)} )

Luego, en el servidor:

 io.on("connection", (socket) => { socket.on("sendMessage", (chatMessage) => { console.log("message sent"); io.to(roomId).emit("receiveMessage", chatMessage); }); }

Cuando hago esto, el mensaje se envía y recibe con éxito, pero sucede muchas veces (consola):

 [] [] [{...}] [{...}] (2) [{...}, {...}]

En el tercer mensaje esto es lo que se registra. En el sexto o séptimo mensaje, toda la página se detiene bruscamente, ya que se registra unas 100 veces.

He probado lo siguiente:

  1. Tener una matriz de dependencias vacía en useEffect() . Esto soluciona los renderizados, pero presenta un nuevo problema. El último mensaje es el único que se guarda y reemplaza al último, por lo que solo puede ver un mensaje a la vez.

  2. Sacándolo de useEffect() todos juntos. Esto solo empeora el problema y provoca aún más repeticiones por mensaje.

Cualquier ayuda sería apreciada. ¡Gracias!

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Tema

Está creando controladores de eventos de socket cuando el estado de chatMessages se actualiza pero no los limpia . Si edita su código o el componente se vuelve a renderizar, etc... entonces se agrega otro controlador de eventos de socket. Los múltiples controladores comenzarán a acumularse y a poner en cola múltiples actualizaciones de estado inesperadas.

Además, dado que las actualizaciones de estado de React se procesan de forma asíncrona, no puede registrar el estado inmediatamente después de poner en cola la actualización y esperar ver el estado actualizado. Use un useEffect separado para esto.

Solución

  1. Agregue una función de limpieza useEffect para eliminar el controlador de eventos y vuelva a incluir la matriz de estado de chatMessages actualizada en la devolución de llamada del controlador.

     useEffect(() => { const handler = (chatMessage) => { setChatMessages([...chatMessages, chatMessage]); } socket.on("receiveMessage", handler); return () => socket.off("receiveMessage", handler); }, [chatMessages]);
  2. Agregue una función de limpieza useEffect , elimine las dependencias para que el efecto se ejecute una vez en el montaje del componente y use una actualización de estado funcional para actualizar correctamente desde el estado anterior en lugar del estado inicial en el gabinete de devolución de llamada.

     useEffect(() => { const handler = (chatMessage) => { setChatMessages(chatMessages => [...chatMessages, chatMessage]); } socket.on("receiveMessage", handler); return () => socket.off("receiveMessage", handler); }, []);

Entre las dos la segunda opción es la solución más óptima, pero la que elijas es tu decisión.

Para registrar las actualizaciones de estado de chatMessages :

 useEffect(() => { console.log(chatMessages); }, [chatMessages]);
about 4 years ago · Juan Pablo Isaza Denunciar

0

Dado que tiene una dependencia de chatMessages , cada vez que cambia chatMessages , crea un nuevo oyente. Y es por eso que se vuelve más y más lento a medida que ingresan más mensajes.

Podrías hacer dos cosas:

  1. Mantienes los chatMessages de chat localmente dentro del método useEffect . Y puede difundir esa matriz y simplemente llamar a setChatMessages con la matriz extendida. Cuando haga esto, puede eliminar la dependencia de chatMessages para useEffect y aún tener todos los mensajes. Como buena práctica, debe devolver una función que elimine el detector de eventos cuando se desmonte el componente.

 const [chatMessages, setChatMessages] = useState([]); const sendChat = (e) => { socket.emit("sendMessage", e.target.elements.message.value); } useEffect(() => { let localMessages = []; const callback = (chatMessage) => { localMessages = [...localMessages, chatMessage]; setChatMessages(localMessages); console.log(localMessages); }; socket.on("receiveMessage", callback); return () => { socket.off("receiveMessage", callback); } }, []); return ( {chatMessages.map((message) => <p>{message}</p>)} )

  1. Probablemente pueda usar useRef para almacenar los valores. Sin embargo, eso no activará la nueva representación de la interfaz de usuario cuando cambie el valor y probablemente eso no sea lo que desea. Así que esta puede no ser una buena opción.
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda