Private Messaging in SocketIO with React Hooks


Client Side:

let { recipientUsername } = useParams();
const [userContext, getUserContext] = useContext(UserContext)
const [messageList, setMessageList] = useState({
    displayed: [],
    raw: []
});

const [recipient, setRecipient] = useState({ username: recipientUsername, online: false })


socket.auth = { "username": localStorage.getItem("username"), "recipient": recipientUsername };
socket.connect()

const handleRequestId = useCallback((requester, username)=>{
    console.log(requester + " requesting Id from: " , username)
    if(socket.auth.username==username){
        console.log("I'm your guy!")
        socket.emit("recieveId", socket.id)
    }
    if(requester==recipientUsername){
        setRecipient({ ...recipient, online: true })
    }
})


const handleReceiveMessage = useCallback((message) => {
    console.log("Message recieved.")
    if (userContext.username == message.recipient) {
        setMessageList((previousState) => ({ ...messageList, raw: [...previousState.raw, message] }))
    }
}, [])

const handleFoundRecipient = useCallback(() => {
    setRecipient({ ...recipient, online: true })
});

const handleFoundSession = useCallback(({ username, sessionId }) => {

})

socket.on("connect_error", (err) => {
    console.log("CONNECT ERR: ", err)
});



useEffect(() => {
    axios_instance.get(`/users/${recipientUsername}/messages`
    ).then((res) => {
        setMessageList({ ...messageList, raw: res.data })
    })

    socket.on("requestId", handleRequestId);
    socket.on("msg", handleReceiveMessage)
    socket.on('foundRecipient', handleFoundRecipient);
    socket.on("session", handleFoundSession)

    return () => {
        socket.disconnect();
    };
}, [])


const handleSubmit = (e) => {
    e.preventDefault();

    const message = {
        body: e.target.body.value,
        recipient: recipientUsername,
        sender: userContext.username,
        date: new Date()
    }


    axios_instance.post(`/users/${recipientUsername}/messages`, message)
        .then((res) => {
            const newArr = [...messageList.raw, res.data]
            setMessageList({ ...messageList, raw: newArr })
            return res.data;
        })
        .then(() => {
            e.target.body.value = ""
            if (recipient.online) {
                console.log("Your recipient is online.")
                socket.emit("msg", message);
            }
        })

}

Server-Side:


io.use((socket, next) => {
 const username = socket.handshake.auth.username;
 const recipient = socket.handshake.auth.recipient
 if (!username || !recipient) {
   return next(new Error("Invalid username"));
 }
 socket.username = username;
 socket.recipient = recipient;
 socket.recipientId = socket.id
 
 next();
});





io.on("connection", (socket) => {
 console.log("Connected!" + `${socket.username}`)

 socket.broadcast.emit("requestId", socket.username, socket.recipient)

 socket.on("recieveId", (id)=>{
   console.log(id)
   socket.recipientId = id
   socket.emit("foundRecipient")
 })


 socket.on("msg", (message) => {
   console.log(message.sender , " is emitting message.")
   socket.to(socket.recipientId).emit("msg", message);
 });
});

Ideally, as I understood it, requestId would be sent to all connected clients that are not the sender. I have looked at the other questions here on the topic and their setup is a little different (no hooks or no react) so I would appreciate any help with what I’m trying to do—as well as an explanation of where exactly my thinking is off.

One person might have chat open before the other, naturally. They join a room corresponding to their own id, and I save recipientId as their own id by default in case requestId fails. That way, they just send messages to their own room when the "msg" event happens on the server-side, and others send messages to their room. I’m hoping to get this so you could chat with more than one person/switch the recipient of a socket but I’m already confused on just connecting two people to one another.

The second person is hitting several key logs. The original on the client side gets the "x is requesting id from y" message and also logs the "I’m your guy!" message, I get the id logged in the second person’s server side "recieveId" function as well as the "x is emitting a msg" log, and I also get the "your recipient is online" log when the second person sends a message (client side). My concern is that the message list never grows; I never hit "Message recieved" on the original.

Any explanation–or help on why this would be, would be greatly appreciated.

Source: React – Stack Overflow

October 23, 2021
Category : News
Tags: node.js | reactjs | socket.io | sockets

Leave a Reply

Your email address will not be published. Required fields are marked *

Sitemap | Terms | Privacy | Cookies | Advertising

Senior Software Developer

Creator of @LzoMedia I am a backend software developer based in London who likes beautiful code and has an adherence to standards & love's open-source.