当用户不在聊天中时如何显示发送的最后一条消息?
Posted
技术标签:
【中文标题】当用户不在聊天中时如何显示发送的最后一条消息?【英文标题】:How to display the lastmessage sent when user is not inside the chat? 【发布时间】:2021-04-17 07:48:34 【问题描述】:我目前有 2 个屏幕,一个是包含我参与的所有聊天的所有消息屏幕,另一个是实际聊天本身的聊天屏幕。
在我的聊天屏幕中,我成功实现了套接字,因此当两个用户同时在聊天屏幕上时,消息就会实时交换。
我的问题:
如果用户 1 在所有消息屏幕上,而用户 2 在聊天中。并且用户 2 向用户 1 发送消息,用户 1 的屏幕不会自动更新消息发送到的对话的最后一条消息,我需要滚动刷新或从一个页面导航到另一个页面才能显示.
有人建议我在 allmessages 屏幕上使用套接字来监听任何事件变化。
在我的数据库中,我有一个对话表和一个消息表。会话表有以下字段:id、user1、user2、postId、lastMessage。 messages 表有以下字段:id、senderID、receiverID、conversationId、message。
客户
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()
/>
服务器
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 );
)
)
我尝试了以下操作,我的控制台日志正在打印,但功能仍然不起作用。
客户
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()
/>
服务器
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
);
)
【问题讨论】:
console.log('User '+socket.id+' connected')
被触发了吗?
@AvivLo 在服务器端是的,当我重新加载我的应用程序并转到所有消息屏幕时,我得到User S1CTDD6euE593ZYaAAB1 connected
user 53 is waiting.
,在客户端我得到waiting for user: 53 to join a conversation
你熟悉事件发射器吗?后端的每个emit
都应该在客户端有一个对应的on
,反之亦然。
@AvivLo 嗨,很抱歉打扰你,但我已经更新了问题,如果你可以请看一下
@kd12345 我建议不要在组件中创建连接,而是使用 redux-sagas 来管理后台 websocket 连接。
【参考方案1】:
我昨天也遇到了同样的问题。但现在它已经修复了。这个应该可以的
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>
)
【讨论】:
您好,感谢您回复我。这是用户准确消息的聊天屏幕本身吗?如果是的话,这对我有用,我的问题是例如。如果 user1 在聊天中并且 user2 在包含所有聊天的屏幕上,如果用户 1 发送消息,则发送的最后一条消息不会自动更新给 user2。你明白我的问题了吗?【参考方案2】::如果用户 1 在所有消息屏幕上,而用户 2 在聊天中。并且用户 2 向用户 1 发送消息,用户 1 的屏幕不会自动更新为消息发送到的会话的最后一条消息
当user2
发送消息时,发出带有socketid
或user1
的事件。在on
事件的帮助下,user1
将收到该消息。只要user1
正在监听事件,user1
在哪个页面上都没有关系。
只需确保发送消息的元数据,以便您能够在客户端区分和处理消息。
【讨论】:
如果两个用户都在聊天中,我的代码可以正常工作并且消息会实时呈现。我的问题是如果 user2 在聊天中并且 user1 在所有聊天的屏幕上并且 user2 向 user1 发送消息,则所有聊天的屏幕都不会自动更新 当用户在所有聊天屏幕上时是否触发事件? 连接事件触发,但 allmessages 屏幕内的 send_message 事件没有 嘿 Abhishek,你能帮我解决一下真的卡住了吗,我的老板今天要我解决这个问题。 当然,只需分享您的回购链接即可。我会努力解决的。以上是关于当用户不在聊天中时如何显示发送的最后一条消息?的主要内容,如果未能解决你的问题,请参考以下文章
Zapier Slack 私人频道:仅当用户在频道中时才发送消息
不在 View Hierarchy 中时重新加载 UITableView/(一般是控制器)