Unable to get the socket id on the front end - reactjs

I need to get each socket's id on the frontend so later I can distinguish each connection. When I print socketRef.current I can clearly see whatever is inside it and even "id" in it but only the "id" is the thing I cannot print from there (if I print "io" or "ids" it works). Why I cannot print the "id" field? Is there a way to get id properly from the backend?
const socketRef = useRef();
useEffect(() => {
socketRef.current = io.connect('http://localhost:5000')
console.log(socketRef.current.id)
}, []);

connect io and on socket connect get socket.id
const socket = io.connect('http://localhost:5000');
socket.on("connect", () => {
console.log(socket.id);
});

I believe need to wait for the connect first:
useEffect(() => {
socketRef.current = io.connect('http://localhost:5000')
socketRef.current.on('connect', ()=> {
console.log(socketRef.current.socket.sessionid);
});
}, []);

Related

Socket call multiple time that first give me ui with update two time then merge with original response

//this is an function that receive real time msg that other user send.
api call to get conversation list...
const handleListMyContact = useCallback(async () => {
const data = await getConversation(authToken);
if (data) {
setListData(data.info);
} else {
console.log("loading data...");
}
}, []);
useEffect(() => {
if (focus) {
handleListMyContact();
}
}, [handleListMyContact, focus]);
const receivePersonalMessage = useCallback((data: any) => {
console.log("data from emit", data);
const contactList: any = listData;
const idxObj = contactList.findIndex((object: any) => {
return object.conversation_id === data.conversation_id;
});
console.log("object find....", idxObj);
contactList.splice(idxObj, 1);
contactList.unshift(data);
console.log("contact list", contactList[0].message);
setListData((prev: any) => [contactList[0], ...prev]);
console.log("clicked...");
handleListMyContact(); // this is my api call that code is above
}, []);
//then I set socket globally. so in useEffect i direct call that socket.on instance.
useEffect(() => {
socket.on("new_conversation_message", receivePersonalMessage);
return () => {
socket.off("new_conversation_message", receivePersonalMessage);
};
}, [socket, receivePersonalMessage]);
whenever other user send the msg at the conversation tab i can see first two response then it render with original one.
// this is log i got from receivePersonalMessage function
object find.... -1
contact list Hi
clicked...
object find.... -1
contact list Hi
clicked...
and the problem is first it shows me hi msg first time in alone then marge with group but actually I want hi msg should be direct update to the group not two times in another user screen then show in orginal group. could you please help me out? I really appreciate if you could help me. Thank you in advance

Socket.io/React Chat App - Connection established

i have two components: where I set the username and room and then I have the component where is the send message and displays the conversation.
When I login on the component, I navigate to the component and trigger the connection with the socket:
const handleClick = (e) => {
e.preventDefault();
navigate("/chatroom", { state: { username, room } });
};
I have two issues regarding the connection with the socket:
-I´ve tried to start the connection inside an useEffect():
export default function ChatRoom() {
const [chatMessage, setChatMessage] = useState("");
const [showmsg, setShowMsg] = useState([]);
const [showObj, setShowObj] = useState([]);
const [submited, setSubmited] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
setShowMsg((oldmsg) => [...oldmsg, chatMessage]);
setChatMessage("");
setSubmited(true);
};
const { state } = useLocation(); //to get data from <Home/> component
useEffect(() => {
const socket = io("http://localhost:3000");
//Message from server
socket.on("message", (msg) => {
setShowObj((oldmsg) => [...oldmsg, msg]);
setSubmited(false);
console.log(showObj);
});
//Message to server
socket.emit("chatMessage", {
user: state.username,
text: showmsg[showmsg.length - 1],
}); //pass the last msg
}, [submited]);
ServerSide:
io.on("connection", (socket) => {
//Welcome current user
socket.emit("message", formatMessage("MiouriChat", "Welcome to the chat!"));
//Broadcast when user connects
socket.broadcast.emit(
"message",
formatMessage("MiouriChat", "A user has joined the chat")
);
//Run when clients disconects
socket.on("disconnect", () => {
io.emit("message", formatMessage("MiouriChat", "A user has left the chat"));
});
//Listen to chat message from client
socket.on("chatMessage", (msg) => {
io.emit("message", formatMessage(msg.user, msg.text));
});
});
This way, everytime I submit a msg ([submited] change), the connection is reseted for obvious reason and get the "welcome" messages everytime it reconects.
If I put the connection outside the useEffect(), the connection reseted everytyme I type a letter on the message input (becouse the state updates.)
What is the best solution for this?
For your initial "welcome" message, you want a useEffect that only runs after the first render of the page as explained in the docs - by specifying an empty dependency array. This is also a really nice place to define the "cleanup" function, where you want to send a "disconnect" message to your server (in fact the cleanup docs even use a chat API as an example!):
useEffect(() => {
const socket = io("http://localhost:3000");
//Message from server
socket.on("message", (msg) => {
setShowObj((oldmsg) => [...oldmsg, msg]);
console.log(showObj);
});
return () => {
socket.emit("disconnect"); // cleanly disconnect from server
};
}, []); // <- Empty dependency array === only runs after initial render
That solves the "welcome message" and "disconnect" problems, and you no longer need the submited state variable. I can't really help you with the rest, but again I commend the useEffect documentation to you, particularly the example which is so applicable to your use case!

React Native websocket object not connected on first attempt

I'm new in react-native and websocket.
const client = new W3CWebSocket(
'url/api/ws/chat/1/' + logID + '/',
);
useEffect(() => {
getID();
getPrevMsgs();
client.onopen = (e) => {
console.log('WebSocket Client Connected',);
};
client.onmessage = message => {
const dataFromServer = JSON.parse(message.data);
console.log('got reply! ', dataFromServer);
if (dataFromServer) {
setMessages(messages => [
...messages,
{msg: dataFromServer.type, sender: dataFromServer.sender},
]);
}
};
scrollHandler();
return () => {
getPrevMsgs();
scrollHandler();
client.close();
};
Now as you see in the above code the issue is that when I come to my chat screen its not connected t WebSocket but when I press ctrl+s then it connects with the websocket, I also try to add this line *const client = newW3CWebSocket('url/api/ws/chat/1/' + logID + '/'); * in useEffect but the still the same thing happens. WHats the reason for that how I can solve this problem.
Problem: How to connect websocket automatically when I come to chatscreen?

Listening socket event in useEffect does not get latest messages

I am working on a React Js announcements component that shows new announcements when pushed from the backend. I am using Socket IO for real time.
So my code looks like this :-
const [ announcements, setAnnouncements ] = useState([])
useEffect(() => {
let socket = SocketIO.connect(ENDPOINT);
setSocket(socket);
socket.on("newAnnouncement", (message) => {
setAnnouncements( [ message, ...announcements ] )
});
axios
.get(getAnnouncementURL)
.then((res) => {
setAnnouncements(res.data.reverse());
})
.catch((err) => console.log(err));
}, []);
The problem in the above code is as I am listening to the event at the first render so the announcements array is empty. So for every new announcement the socket gets, this ([ message, ...announcements ]) becomes [ message ] ( as announcements is empty ) and all my
previous announcements gets flushed and I see only the new messages
Change your code to
setAnnouncements(prev => [ message, ...prev ] )

React/Socket.io - Client emits to all other clients only once and then only emits to itself after that

Running into an issue with React/Socket.io. I have two different socket emitters/listeners: one for a chat, and one for keeping track live changes to the application. I have two separate windows running localhost. The issue is when i emit a change on one window, the other window can receive that change the first time but never again (i.e. get first chat message but none that follow). After that first emit/receive, the sending client starts to receive its own emitters.
front end code:
`
socket = io("localhost:3002");
componentDidMount() {
//get id from url
const { id } = this.props.match.params;
//join specific room for project
this.socket.on("connect", () => {
this.socket.emit("room", this.projectId);
});
//listener for incoming messages
this.socket.on("RECEIVE_MESSAGE", (data) => {
this.props.addChat(this.projectId, data);
});
this.socket.on("UPDATE_PROJECT", () => {
console.log("update");
this.props.fetchProject(id);
});
}
emitTaskChange = () => {
this.socket.emit("TASK_CHANGE", { data: null });
};
onChatSubmit = (e) => {
e.preventDefault();
//create object with current user as author, message, and a timestamp
const chat = {
author: this.props.currentUser.name,
message: this.state.newChat,
createdAt: new Date().toLocaleString(),
};
//send message through socket
this.socket.emit("SEND_MESSAGE", chat);
//call action creator to add new chat
this.props.addChat(this.projectId, chat);
this.setState({ currentMessage: "" });
};
handleTaskEdit = (taskId, currentStatus) => {
const newStatus = currentStatus === "todo" ? "inprogress" : "completed";
this.props.editTask(this.projectId, taskId, newStatus);
this.emitTaskChange();
};
`
backend code:
`
const io = socket(server);
//create separate chat rooms using project id
io.on("connection", (socket) => {
socket.on("room", (room) => {
socket.join(room);
socket.in(room).on("SEND_MESSAGE", (message) => {
socket.emit("RECEIVE_MESSAGE", message);
});
socket.in(room).on("TASK_CHANGE", (data) => {
socket.emit("UPDATE_PROJECT", data);
});
});
`
found the error:
had to change the server-side code from socket.on and instead use the io object that was initialized such as io.sockets.on

Resources