Socket.io - how to display the lastmessage sent when user is not inside the chat?

狂风中的少年 提交于 2021-01-29 21:11:20

问题


i currently have 2 screens an all messages screen which includes all the chats i participated in and a chat screen which is the actual chat itself.

In my chat screen i successfully implemented sockets, so when both users are on the chat screen at the same time messages are getting exchanged live.

My problem:

Example: if user 1 is on the allmessages screen and user 2 is inside the chat. And user 2 sends user 1 a message, user 1's screen does not automatically update with the last message for the conversation the message was sent to, I need to either scroll to refresh or navigate from one page to the other in order for it to appear.

I got suggested to use socket on the allmessages screen to listen to any event change.

In my database i have a conversations table and a messages table:

the conversation table has the following fields: id,user1,user2,postId,lastMessage

the messages table has the following fields:id, senderID,receiverID, conversationId, message

CLIENT

Chatscreen.js

useEffect(() => {
const newsocket =io.connect("IP:PORT")
setMessages(message.Messages)

newsocket.on('connect', msg => {
console.log(`user: ${user.id} has joined conversation ${message.id}`)
setSocket(newsocket)
newsocket.emit('subscribe', message.id);
 });

newsocket.on("send_message", (msg) => {
console.log("this is the chat messages:", msg);
setMessages(messages => messages.concat(msg))
});

return(()=>newsocket.close());

}, []);

const onSend = (ConversationId,senderId,receiverId,message) => {
console.log("sent")
const to = (user.id===route.params.message.user1? 
route.params.message.user2:route.params.message.user1)
socket.emit('message', { to: to, from: user.id, message,ConversationId });
setText("")
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
};

allmessagesScreen.js

const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const[page,setPage]=useState(0);
const [refreshing, setRefreshing] = useState(false);

const loadPosts = async () => {
setLoading(true);
const response = await messagesApi.getMessages();
setLoading(false);

if(refreshing) setRefreshing(false);

if (!response.ok) return setError(true);

setError(false);

setPosts(response.data)
};

useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
loadPosts();
});
return unsubscribe;
}, [navigation]);

return(

<FlatList
    data={posts}
    keyExtractor={(post) => post.id.toString()}
    renderItem={({ item,index }) => (
      <MessagesList
      title={item.Post.title}
        subTitle={item.Messages[0].message}
        onPress={() => navigation.navigate(routes.CHAT,{message:item,index})}
      />
    )}
    refreshing={refreshing}
    onRefresh={() => {
      loadPosts()
    }}
  />

SERVER

io.on('connection',(socket)=>{
console.log('User '+socket.id+' connected')

socket.on('subscribe', (room)=> {
console.log('joining room', room);
socket.join(room);
});

socket.on('message', (data) => {
console.log(data)
console.log('sending room post',data.ConversationId)
io.sockets.in(data.ConversationId).emit('send_message', { message: 
data.message, receiverId: 
data.to,senderId:data.from,conversationId:data.ConversationId });
})
})

UPDATE

i gave the following a try, my console logs are getting printed but the functionaility still doesnt work.

CLIENT

Chatscreen.js

useEffect(() => {
const newsocket =io.connect("IP:PORT")
setMessages(message.Messages)

newsocket.on('connect', msg => {
console.log(`user: ${user.id} has joined conversation ${message.id}`)
setSocket(newsocket)
newsocket.emit('subscribe', message.id);
 });

newsocket.on("send_message", (msg) => {
console.log("this is the chat messages:", msg);
setMessages(messages => messages.concat(msg))
});

return(()=>newsocket.close());

}, []);

const onSend = (ConversationId,senderId,receiverId,message) => {
console.log("sent")
const to = (user.id===route.params.message.user1? 
route.params.message.user2:route.params.message.user1)
socket.emit('message', { to: to, from: user.id, message,ConversationId });
setText("")
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
};

allmessagesScreen.js

const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const[page,setPage]=useState(0);
const [refreshing, setRefreshing] = useState(false);

const loadPosts = async () => {
setLoading(true);
const response = await messagesApi.getMessages();
setLoading(false);

if(refreshing) setRefreshing(false);

if (!response.ok) return setError(true);

setError(false);

setPosts(response.data)
};

  useEffect(() => {
  const newsocket =io.connect("http://ip:port")
  loadPosts()

   newsocket.on('connect', msg => {
    console.log(`waiting for user: ${user.id} to join a conversation`) //this gets printed 
    setSocket(newsocket)
    newsocket.emit('waiting', user.id);
   });

 newsocket.on("send_message", (msg) => {
  console.log("this is the last message:", msg); //this doesnt get printed 
});
   }, []);

return(

<FlatList
    data={posts}
    keyExtractor={(post) => post.id.toString()}
    renderItem={({ item,index }) => (
      <MessagesList
      title={item.Post.title}
        subTitle={item.Messages[0].message}
        onPress={() => navigation.navigate(routes.CHAT,{message:item,index})}
      />
    )}
    refreshing={refreshing}
    onRefresh={() => {
      loadPosts()
    }}
  />

SERVER

io.on('connection',(socket)=>{
console.log('User '+socket.id+' connected')//this gets printed 

socket.on('subscribe', (room)=> {
console.log('joining room', room);//this gets printed 
socket.join(room);
});

socket.on('message', (data) => {

console.log(data) //this gets printed 
console.log('sending room post',data.ConversationId) //this gets printed 
io.sockets.in(data.ConversationId).emit('send_message', { message: 
data.message, receiverId: 
data.to,senderId:data.from,conversationId:data.ConversationId }); 
})

socket.on('waiting', (user)=> {
console.log('user', user, 'is waiting.');//this gets printed 
});

})

回答1:


I've just got same problem yesterday. But now it has been fixed. This one should works

import React, { useEffect, useState, useRef } from 'react'
import socket from 'socket.io-client'

const Chatbox = () => {
  const [chats, setChats] = useState([])
  const [message, setMessage] = useState('')
  const socketClientRef = useRef()

  useEffect(() => {
    const client = socket("http://localhost:3002");
    client.on("connect", () => {
      console.log('connected')
    })
    client.on("disconnect", () => {
      console.log('diconnected')
    });
    client.on("chat", message => {
      setChats(prevChats => [...prevChats, message])
      // INSTEAD OF:
      // setChats([...chats, message])
    });
    socketClientRef.current = client
    return () => {
      client.removeAllListeners()
    }
  }, [])

  const handleSend = async () => {
    socketClientRef.current.emit('chat', {
      room: `event-${eventId}`,
      message
    })
    setMessage('')
  }


  return (
    <div>
      <div>
        <h1>Messages</h1>
        {chats.map(chat => (
          <div>{chat}</div>
        ))}
      </div>
      <div>
        <input value={message} onChange={e => setMessage(e.target.value)} />
        <button onClick={handleSend}>Send</button>
      </div>
    </div>
  )
}



回答2:


: if user 1 is on the allmessages screen and user 2 is inside the chat. And user 2 sends user 1 a message, user 1's screen does not automatically update with the last message for the conversation the message was sent to

When user2 sends a message, emit an event with socketid of user1. The message will be received by user1 with help the on event. It doesn't matter on which page user1 will be as long as user1 is listening to the event.

Just make sure to send the metadata of the messages so that you will be able to differentiate and handle the messages on client side.



来源:https://stackoverflow.com/questions/65682609/socket-io-how-to-display-the-lastmessage-sent-when-user-is-not-inside-the-chat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!