React Native Socket.io 只在服务器和客户端重新加载时发出消息

n9vozmp4  于 2023-03-31  发布在  React
关注(0)|答案(1)|浏览(175)

我有这个悬而未决的问题几天了。我正在构建一个Expo React Native应用程序与Node.js后端和MYSQL与Sequelize为数据库。该应用程序具有消息传递功能,我用socket.io处理。在服务器和客户端重新加载时,Socket.io立即发出消息。如果您作为用户离开聊天室并进入新的聊天室,在重新加载服务器和客户端之前,您将不会收到即时消息。这就是它现在的工作方式。奇怪的是,当我在发送新消息时对来自socket.io数据的数据使用console.log()时,我会看到发出的消息。然而,它根本无法显示在屏幕上。我已经做了我能想到的一切。我不知道问题是来自React Native还是服务器端。下面是代码示例:
服务器端:

import * as socketio from "socket.io";
 export const io = new socketio.Server();

  const socketapi = {
   io: io
   };
  
   let users: userSocketAttributes[] = [];

      io.on('connection', (socket)=>{
        console.log('A user connected via socket.io');
        socket.on("addUser", userId=>{
        const userValues = {
            userId: userId as string,
            socketId: socket.id
          }
           addUser(userValues);
           io.emit("getUsers", users)
         });
              socket.on("sendMessage", async (messageAttributes: socketMessageAttributes, )=>{
        const user = findUser(messageAttributes.recieverId);
        
        const authToken = JWT_Helper_verify(messageAttributes.auth) as JwtPayload;
                    
       try {
        const userid = await CreateCustomer.findOne({where:{id: authToken?.id}});
        const support = await CreateCustomer.findOne({where: {user_username: 'support'}});

        
        io.to(user?.socketId as string).emit("getMessage", messageAttributes)
       } catch (error) {
        return console.log(error)
       }
        })
        //disconect
        socket.on("disconnect", ()=>{
        console.log("disconnected");
        removeUser(socket.id);
        io.emit("getUsers", users)

         })
         })

server.js

import socketapi from "./socket";
 
  const server = http.createServer(app);

  socketapi.io.attach(server)
   const startServer = ()=>{

   server.listen(port, ()=>{
    console.log(`server is listening on ${port}`)
  })
 }
startServer()

客户端:

const socket = useRef()
  //fetch messages from database
   const fetchMessages = async()=>{

        try {
         const res = await axios.get(`${BASE_URL}/conversation/${data?.conversation?.id}`, { 
         withCredentials: true,
             headers:{authorization: `Bearer ${token}`}})
                setChatMessages(res?.data?.CreateMessageModels);
               
        } catch (error) {
         
        }
     }

     //users to exchange messages
 useEffect(()=>{
   
    socket.current = io(socket_URL);
    socket.current.emit('addUser', userDetails?.role === 'support'? data?.conversation?.recieverId: userDetails?.id);
    socket.current.on("getUsers", users =>{
       console.log(users, 'socket')
   }); 
   
}, [data?.conversation?.id])

//useEffect for fetching messages from database
 useEffect(()=>{
    fetchMessages()
}, [])

//Listens to socket.io emitted messages
  useEffect(()=>{
   
    socket.current.on("getMessage", (item)=>{
        
        if(data?.conversation?.id == item?.conversationId){
           
            setChatMessages([...chatMessages, item])
        }    
    })
   });

我能做些什么来解决这个问题?

vs91vp4v

vs91vp4v1#

这是我在REACT应用程序中使用socket.io客户端的方式。

const WSAPI_URI = "wss://example.org"
export const wsContext = React.createContext({} as any);

export default function WsProvider({
  children,
}: {
  children: ReactNode;
}): ReactElement {
  const [webSocket, setWebSocket] = React.useState<any>(null);

  React.useEffect(() => {
    const socket = io(WSAPI_URI, {
      query: {
        accesstoken: localStorage.getItem("@myapp/access_token"),
      },
      reconnection: true,
      transports: ["websocket"],
    });
    setWebSocket(socket);
  }, []);

  React.useEffect(() => {
    if (!webSocket) return;

    return () => webSocket.off();
  }, [webSocket]);

  return <wsContext.Provider value={webSocket}>{children}</wsContext.Provider>;
}

function SomeComponent() {
  const ws = useContext(wsContext);

  useEffect(() => {
    ws.on(`MYTOPIC`, (data: string) => {
       // my logic
    });
    return () => {
      ws?.off(`MYTOPIC`);
    };
  }, [ws])

  return <></>
}

function MyAPP() {
  return <WsProvider>
      <SomeComponent/>
  </WsProvider>
}

相关问题