node.js - 使用 socket.io react 本地一对一对话

标签 node.js react-native socket.io sequelize.js

我目前有一个 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>
)
服务器端
索引.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))
 })
 }, []);

最佳答案

您当前在每次状态更改时创建新连接.. const socket =io.connect(socketurl)您有一个 useEffect 回调,这将是放置连接逻辑的合乎逻辑的位置,目前您只监听一次连接,但创建多个连接,因此永远不会在这些新连接上调用您的 'connection' 事件。但是无论如何你只想连接一次,所以我们只需要将连接逻辑也放在 useEffect 中,而不仅仅是连接事件。
因为连接到套接字是异步的,所以您需要在渲染之前等待连接。所以我们可以做的是将套接字存储在状态中,当我们获得连接集套接字状态时,这将使用现在有效的套接字触发重新渲染。
例如。

const [socket, setSocket] = useState(null);
...
useEffect(() => {
   const socket = io.connect(socketurl)
   setMessages(messages);
   newsocket.on('connect', msg => { //connect not connection
      console.log('i have joined')
      setMessages(messages=>messages.concat(msg));
      setSocket(newSocket);
   });
   //might make sense to close the socket too, 
   //otherwise a memory leak. 
   return () => newSocket.close();
}, [route, navigation]); 


if (!socket) {
  //we don't have a socket yet,
  return "loading..";
} else {
  // we have a socket, 
  const onSend = (ConversationId,senderId,receiverId,message) => {...
  ....
  // now render..
  return (
    <Text>{.........

关于node.js - 使用 socket.io react 本地一对一对话,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65277256/

相关文章:

javascript - 异步函数作为 socketio 监听器的处理程序

node.js - 如何以编程方式安排 AWS lambda 函数在事件发生后运行 X 时间?

ios - 如何在react-native中调试 `native Objective C code`?

reactjs - "left side of comma operator.."渲染的html内容错误

javascript - 如何通过应用过滤器来渲染Reducer?

php - 如何在 php 站点上的专用 Node.js 服务器上使用 Socket.io?

node.js - 在 Node.js 中组合两个 Transform 流

javascript - 未找到 socket.io.js

javascript - Node.js/Koa2 服务器 - 在请求后几分钟执行作业

node.js - Meteor JS 中是如何实现热重载的?