I am trying to practice socket.io
with React.js
so I am trying to send messages between two clients, however I'm struggling with displaying the messages. I want to show the past messages sent. Now I was thinking about doing it as an array because a state didn't work. When console logging the array it shows up in the console but never renders out
import { useEffect, useState } from "react";
import io from "socket.io-client";
import "./App.css";
let socket;
const CONNECTION_PORT = "localhost:3001/";
function App() {
const [loggedIn, setLoggedIn] = useState(false);
const [room, setRoom] = useState("");
const [userName, setUserName] = useState("");
const [message, setMessage] = useState("");
var itemArray = [];
useEffect(() => {
//connect to the socket
socket = io(CONNECTION_PORT);
socket.on("receive-message", (data) => {
itemArray.push(data);
console.log("Pong");
console.log(itemArray);
});
//receiving messages
socket.on("authentication", (bool) => {
if (bool === true) {
setLoggedIn(true);
}
});
}, [CONNECTION_PORT]);
//Sending a request to join the room
const connectToRoom = () => {
socket.emit("join-room", room, userName);
};
const sendMessage = () => {
socket.emit("send-message", message);
};
return (
<div className="App">
{!loggedIn ? (
<div className="login">
<input
type="text"
placeholder="Name..."
onChange={(e) => {
setUserName(e.target.value);
}}
/>
<input
type="text"
placeholder="Room..."
onChange={(e) => {
setRoom(e.target.value);
}}
/>
<button onClick={connectToRoom}> Enter Chat</button>
</div>
) : (
<div>
<input
type="text"
placeholder="Send Message..."
onChange={(e) => {
setMessage(e.target.value);
}}
/>
<button onClick={sendMessage}>Send Message</button>
<div>
{itemArray.map((data) => {
console.log(data);
})}
</div>
</div>
)}
</div>
);
}
export default App;
The array is updating, but there is nothing to tell React to render the update. Any of these changes will cause the component to render again:
React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring the DOM to the desired state.
You are updating an array variable within the component, but this won't trigger a render. Move the array into state:
const [messages, setMessages] = useState([]);
...
useEffect(() => {
...
socket.on("receive-message", (data) => {
// update the state which triggers a render
setMessages(prevState => [...prevState, data]);
});
}, [CONNECTION_PORT]);