【发布时间】:2021-03-24 09:33:33
【问题描述】:
我目前有一个 react native 应用程序,其中 nodejs express Sequelize 作为我的后端,postgres 作为我的数据库。
因此,在每个帖子旁边的帖子屏幕上,我有一个文本输入和一个按钮,当前用户可以在其中向帖子的用户发送初始消息。一旦按下按钮,这两个用户之间关于这篇文章的对话就会在我的数据库中创建并存储在我的对话表中,并且发送的消息条目也存储在我的消息表中。
我已经在这两个用户之间实现了双向通信。但我的问题是我需要刷新应用程序才能向用户显示当前用户发送的消息并向接收用户显示收到的消息。
我已经研究了一段时间,并试图了解如何使用 socket.io 实现此功能,但无处可去。
客户端
这是我的聊天屏幕
function ChatScreen({route,navigation}) {
const message = route.params.message;
const [messages, setMessages] = useState(message.Messages);
const [text, setText] = useState('');
const { user } = useAuth();
const [socket, setSocket] = useState(null);
useEffect(() => {
const newsocket =io.connect(socketurl)
setMessages(messages);
newsocket.on('connection', msg => {
console.log('i have joined')
setMessages(messages=>messages.concat(msg))
setSocket(newsocket)
})
return()=>newsocket.close;
}, []);
const updateText=(text)=>{
setText(text);
}
const onSend = (ConversationId,senderId,receiverId,message) => {
console.log("sent")
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
setText("")
socket.emit('message', { to: (user.id===route.params.message.user1 ?
route.params.message.user2 : route.params.message.user1), from:
user.id, message,ConversationId });
};
return(
<Text>{user.id === message.Recipient.id ?
message.Creator.name:message.Recipient.name}</Text>
<KeyboardAvoidingView
style={{
display: "flex",
flex: 1,
}}
behavior={Platform.OS === "ios" ? "padding" : null}
keyboardVerticalOffset={Platform.OS === "ios" ? 25 : 0}
>
<FlatList
inverted
data={message.Messages}
keyExtractor={(message) => message.id.toString()}
renderItem={({item,index})=>(
<MessageBubble
text={item.message}
mine={item.senderId !== user.id}
/>
)}/>
<View style={styles.messageBoxContainer}>
<TextInput
style={styles.messageBox}
placeholder="Message..."
multiline
clearButtonMode="while-editing"
onChangeText={updateText}
value={text}
autoCorrect={false}
/>
<TouchableOpacity onPress={onSend}>
<Text style={styles.send}>Send</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
服务器端
index.js
const express = require("express");
const app = express();
const http = require("http");
const socketio = require("socket.io")
const server=http.createServer(app);
const io =socketio(server)
io.on("connection", socket => {
socket.on('message', (data) => {
socket.join(data.ConversationId);
io.sockets.in(data.to).emit('send_message', { message: data.message,
to: data.to });
});
});
const port = process.env.PORT || config.get("port");
server.listen(port, function () {
console.log(`Server started on port ${port}...`);
});
目前,当我发送消息时,消息会存储在我的数据库中,但我的聊天不会立即更新(即不实时),我需要刷新我的应用程序并显示消息。
有人可以帮我检查一下我目前拥有的套接字的实现是否正确,如果正确,我如何立即渲染我的平面列表?
更新
我认为我的 useEffect 有问题,因为当我打开聊天时,我没有在控制台中看到“我已加入”:
useEffect(() => {
setMessages(messages);
socket.on('connect', msg => {
console.log('i have joined')
setMessages(messages=>messages.concat(msg))
})
}, []);
【问题讨论】:
-
两个用户必须向同一个端口发送/发送事件。在前端定义服务器套接字端口和用户登录时,他们将事件发送到该套接字以获取新条目。现在,当用户开始对话时,它会再次创建一个包含另一个用户 ID 的新条目。我使用套接字作为通知。
-
@VinitBhavsar 你有一个如何使用套接字的例子,因为这是我第一次使用它们吗?
-
我没有任何服务器端设置套接字的经验,我们在前端所做的只是 const socket = io("socket port address");像这样发出事件 socket.emit("send_request",data);套接字事件监听器 socket.on("get_request", () => {})
-
所以当 send_request 被调用时,get_request 会得到更新
-
那么,我应该在哪里创建我的套接字?
标签: node.js react-native socket.io sequelize.js