As a new developer, I recently built a chat application using socket io. In my code, I have the useEffect hook set to only change when the socket changes. However, I also have setMessage within the body of useEffect(), with socket as a dependency. Unfortunately, this setup doesn't seem to work as expected and keeps re-running infinitely.
import React from 'react';
import ScrollToBottom from 'react-scroll-to-bottom';
import { useState, useEffect } from 'react';
function Chat({ socket, username, room }) {
const [currentMessage, setCurrentMessage] = useState("");
const [messageList, setMessageList] = useState([]);
const sendMessage = async () => {
if (currentMessage !== "") {
const messageData = {
room: room,
author: username,
message: currentMessage,
time: `${new Date(Date.now()).getHours()}:${new Date(Date.now()).getMinutes()}`
};
await socket.emit("send_message", messageData);
setMessageList((list) => [...list,messageData]);
}
};
useEffect(() => {
socket.on("receive_message", (data) => {
setMessageList((list) => [...list, data]);
setCurrentMessage("");
});
}, [socket]);
return (
<div className='chat-window'>
<div className='chat-header'>
<p>Live Chat</p>
</div>
<div className='chat-body'>
<ScrollToBottom className='message-container'>
{messageList.map((messageContent) => {
return (
<div className='message' id={username === messageContent.author ? "you" : "other"}>
<h1>{messageContent.message}</h1>
</div>
);
})}
</ScrollToBottom>
</div>
<div className='chat-footer'>
<input type="text" value={currentMessage} placeholder='Hey..' onChange={(event) => {
setCurrentMessage(event.target.value);
}}
onKeyPress={(event) => {
event.key === 'Enter' && sendMessage();
}}/>
<button onClick={sendMessage}>►</button>
</div>
</div>
);
}
export default Chat;
Is there a way to prevent the useEffect function from re-rendering unnecessarily?