【发布时间】:2021-03-27 05:48:31
【问题描述】:
我刚刚在我的 react native 和 nodejs 项目中设置了我的套接字,但我的平面列表在发送消息时仍然没有立即更新,我需要刷新应用程序才能更新。
我认为通过使用套接字这将起作用,但它仍然不起作用。每当我用户打开聊天时,我都会得到例如。 user: 1 在控制台中加入了会话 1,这表明套接字正在工作。
客户端
function ChatScreen({route,navigation}) {
const message = route.params.message;
const [messages, setMessages] = useState(message.Messages);
const [text, setText] = useState('');
const [socket, setSocket] = useState(null);
const { user } = useAuth();
const index = route.params.index;
const updateView = route.params.updateView;
useEffect(() => {
const newsocket =io.connect(socketURL)
setMessages(messages);
newsocket.on('connect', msg => {
console.log(`user: ${user.id} has joined conversation ${message.id}`)
setMessages(messages=>messages.concat(msg))
setSocket(newsocket)
});
return()=>newsocket.close;
}, []);
const onSend = (ConversationId,senderId,receiverId,message) => {
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
setText("")
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 });
};
const updateText=(text)=>{
setText(text);
}
return (
<FlatList
inverted
data={message.Messages}
keyExtractor={(message) => message.id.toString()}
renderItem={({item,index})=>(
<>
<Text>
{moment(item.createdAt).fromNow()}
</Text>
<MessageBubble
text={item.message}
mine={item.senderId !== user.id}
/>
</>
)}
/>
<View style={styles.messageBoxContainer}>
<TextInput
onChangeText={updateText}
value={text}
/>
<TouchableOpacity
onPress={()=>{onSend(message.id,user.id,(user.id===message.user1?
message.user2:message.user1),text)}}>
</TouchableOpacity>
</View>
);
}
服务器端
const express = require("express");
const app = express();
const http = require("http");
const socket = require("socket.io")
const server=http.createServer(app);
const io =socket(server)
io.on('connection', (socket) => {
console.log("connected")
socket.on('message', (data) => {
console.log(data)
socket.join(data.ConversationId);
io.sockets.in(data.to).emit('send_message', { message:
data.message, to: data.to });
});
});
更新
客户端
const message = route.params.message;
const [messages, setMessages] = useState([]);
const [text, setText] = useState('');
const [socket, setSocket] = useState(null);
const { user } = useAuth();
useEffect(() => {
const newsocket =io.connect("http://192.168.1.103:9000")
newsocket.on('connect', msg => {
console.log(`user: ${user.id} has joined conversation
${message.id}`)
setSocket(newsocket)
setMessages(message.Messages)
});
newsocket.on("send_message", (msg) => {
console.log("this is the chat message:", msg);
setMessages([ { ...message.Messages },...messages]);
});
return()=>newsocket.close;
}, []);
const onSend = (ConversationId,senderId,receiverId,message) => {
console.log("sent")
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
setText("")
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 });
};
const updateText=(text)=>{
setText(text);
}
<FlatList
inverted
data={messages}
keyExtractor={(message) => message.id.toString()}
renderItem={({item,index})=>(
<>
<Text>
{moment(item.createdAt).fromNow()}
</Text>
<MessageBubble
text={item.message}
mine={item.senderId !== user.id}
/>
</>
)}
bounces={false}
/>
<View style={styles.messageBoxContainer}>
<TextInput
onChangeText={updateText}
value={text}
/>
<TouchableOpacity
onPress={()=>{
onSend(
message.id,
user.id,
(user.id===message.user1?message.user2:message.user1),
text
)}}
>
<Text>Send</Text>
</TouchableOpacity>
</View>
服务器端
io.on('connection', (socket) => {
console.log("connected")
socket.on('message', (data) => {
console.log(data)
socket.emit('send_message', { message: data.message, receiverId:
data.to,senderId:data.from,conversationId:data.ConversationId })
});
});
使用更新的代码,当我打开聊天时,我会得到
user: 43 has joined conversation 4 ---- on client side console
connected ---- on server side console
使用更新的代码,当我发送消息时,我得到了
this is the chat message: Object {
"conversationId": 25,
"message": "You",
"receiverId": 47,
"senderId": 43,
} --- in my client side console
{ to: 47, from: 43, message: 'You', ConversationId: 25 } ---- server
side console
然后我得到一个错误
undefined is not an object (evaluating 'message.id.toString')
我认为我的问题是我没有正确发出消息 ID,因此我的平面列表不知道它。要获取消息 ID,我需要先将消息存储在 db 中
新更新
客户端
const message = route.params.message;
const [messages, setMessages] = useState([]);
const [text, setText] = useState('');
const [socket, setSocket] = useState(null);
const { user } = useAuth();
useEffect(() => {
const newsocket =io.connect(socketURL)
newsocket.on('connect', msg => {
console.log(`user: ${user.id} has joined conversation
${message.id}`)
setSocket(newsocket)
setMessages(message.Messages)
});
newsocket.on("send_message", (msg) => {
console.log("this is the chat message:", msg);
const data = [...messages];
console.log(data)
data.push(msg);
setMessages(data);
});
return(()=>newsocket.close());
}, []);
const onSend = (ConversationId,senderId,receiverId,message) => {
console.log("sent")
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
setText("")
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 });
};
const updateText=(text)=>{
setText(text);
}
<FlatList
inverted
data={messages}
keyExtractor={(item,index)=>index.toString()}
renderItem={({item,index})=>(
<>
<Text>
{moment(item.createdAt).fromNow()}
</Text>
<MessageBubble
text={item.message}
mine={item.senderId !== user.id}
/>
</>
)}
bounces={false}
/>
<View style={styles.messageBoxContainer}>
<TextInput
onChangeText={updateText}
value={text}
/>
<TouchableOpacity
onPress={()=>{
onSend(
message.id,
user.id,
(user.id===message.user1?message.user2:message.user1),
text
)}}
>
<Text>Send</Text>
</TouchableOpacity>
</View>
服务器端
io.on('connection', (socket) => {
console.log("connected")
socket.on('message', (data) => {
console.log(data)
socket.emit('send_message', { message: data.message, receiverId:
data.to,senderId:data.from,conversationId:data.ConversationId })
});
});
现在在我发送消息时使用新的更新代码,只有新消息会呈现给发送者,而没有先前的消息,并且接收者在聊天时不会收到任何内容。
【问题讨论】:
-
您监听的唯一内容是连接,您还想监听消息,.. 例如。
newsocket.on('msg', => .....)在这个事件中你可以调用setMessages,你的服务器端当然也需要发出这些新消息。 -
@Keith 我已经在我的服务器端为消息发送了一个套接字,我已将它添加到上面的代码中
-
但是您没有在客户端监听套接字更新,是吗?从您的代码中,您只需侦听客户端上的连接。此外,您必须使用收到的每条消息更新状态/道具,但现在您从来自路由的
message.Messages获取数据。 -
@Konstantin 在我的客户端 onSend 函数中我使用 socket.emit 进行消息事件
-
Emitting 用于发送消息,
socket.on(smth)用于接收套接字消息。您在哪里收到它们?
标签: react-native