As per the documentation one to one chat happens when we emit the message to the specific socket.id. for example
io.to(socket.id).emit("event","message")
This will only work if two users are connected at the same time. If we are to add chat feature in our application where registered users can chat with each other (1-1).What is the optimal solution for that.I have implemented the chat using io.to(socket.id),but when one of the user is offline socket.id is not available.
-----------------------------------Client-------------------------------
function Chat() {
const [conversations, setConversations] = useState([]);
const [currentChat, setCurrentChat] = useState(null);
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState("");
const [arrivalMessage, setArrivalMessage] = useState(null);
const scrollRef = useRef();
const socket = useRef();
const client = isAuthenticated()
const clientId = isAuthenticated().client._id;
const token = isAuthenticated().client.token
console.log(clientId)
useEffect(() => {
socket.current = io("ws://localhost:8900");
socket.current.on("getMessage", (data) => {
setArrivalMessage({
sender: data.senderId,
text: data.text,
createdAt: Date.now(),
});
});
}, []);
useEffect(() => {
arrivalMessage &&
currentChat?.members.includes(arrivalMessage.sender) &&
setMessages((prev) => [...prev, arrivalMessage]);
}, [arrivalMessage, currentChat]);
useEffect(() => {
socket.current.emit("addUser",clientId );
}, [client]);
useEffect(() => {
getconversation(clientId,token).then((data)=>{
if(data.error){
console.log(data.error)
}else{
console.log(data)
setConversations(data)
}
})
}, [])
useEffect(() => {
const getMessages = async () => {
try {
const res = await axios.get("http://localhost:8080/api/messages/" + currentChat?._id);
setMessages(res.data);
} catch (err) {
console.log(err);
}
};
getMessages();
}, [currentChat]);
useEffect(() => {
scrollRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
const handleSubmit = async (e) => {
e.preventDefault();
const message = {
sender:clientId,
text: newMessage,
conversationId: currentChat._id,
};
const receiverId = currentChat.members.find(
(member) => member !== clientId
);
socket.current.emit("sendMessage", {
senderId: clientId,
receiverId,
text: newMessage,
});
try {
const res = await axios.post("http://localhost:8080/api/messages", message);
setMessages([...messages, res.data]);
setNewMessage("");
} catch (err) {
console.log(err);
}
};
-------------------------Server-----------------------------------------
const io = require("socket.io")(8900, {
cors: {
origin: "http://localhost:3000",
},
});
let users = [];
const addUser = (userId, socketId) => {
!users.some((user) => user.userId === userId) &&
users.push({ userId, socketId });
};
const removeUser = (socketId) => {
users = users.filter((user) => user.socketId !== socketId);
};
const getUser = (userId) => {
return users.find((user) => user.userId === userId);
};
io.on("connection", (socket) => {
//when connect
console.log("a user connected."+socket.id);
//take userId and socketId from user
socket.on("addUser", (userId) => {
addUser(userId, socket.id);
io.emit("getUsers", users);
});
//send and get message
socket.on("sendMessage", ({ senderId, receiverId, text }) => {
console.log("receiverid=====>>>",receiverId)
console.log("users ",users)
const user = getUser(receiverId);
console.log("userSocket Id",user)
io.to(user.socketId).emit("getMessage", {
senderId,
text,
});
});
//when disconnect
socket.on("disconnect", () => {
console.log("a user disconnected!");
removeUser(socket.id);
io.emit("getUsers", users);
});
});