Reactjs 如何在每次页面刷新时阻止socketio重新连接

Reactjs 如何在每次页面刷新时阻止socketio重新连接,reactjs,express,socket.io,Reactjs,Express,Socket.io,我试图从以下代码编写私有消息传递socketio示例:in React。但是,我认为我初始化的连接不正确,因为每次页面刷新时,它都会创建一个新的连接。我真的不知道从这里到哪里去。后端与上面的repo相同,这是聊天组件 import React, { useEffect, useRef, useState } from "react"; import User from "./User"; import MessagePanel from "./M

我试图从以下代码编写私有消息传递socketio示例:in React。但是,我认为我初始化的连接不正确,因为每次页面刷新时,它都会创建一个新的连接。我真的不知道从这里到哪里去。后端与上面的repo相同,这是聊天组件

import React, { useEffect, useRef, useState } from "react";
import User from "./User";
import MessagePanel from "./MessagePanel";
import { io } from "socket.io-client";

import socketIo from '@/utils/socket'

function useSocket(url, username) {
  const [socket, setSocket] = useState(null)

  useEffect(() => {
    const socketIo = io(url, { auth:{username}, autoConnect: true });
    setSocket(socketIo)

  }, [])

  return socket
}

export default function Chat(props) {
  const [selectedUser, setSelectedUser] = useState(null)
  const [users, setUsers] = useState([])
  const API_URL='http://localhost:5000'
  const socket = useSocket(API_URL, props.name)

  useEffect(() => {
    const handleConnect = () => {
      console.log("A user has connected")
      const tempUsers = [...users]
      tempUsers.forEach((user) => {
        if (user.self) {
          user.connected = true
        }
      });
      setUsers(tempUsers)
    }

    if (socket) {
      const sessionID = localStorage.getItem("sessionID");

      if (sessionID) {
        socket.auth =  {...socket.auth, sessionID };
        // socket.connect();
      }

      socket.on("session", ({ sessionID, userID }) => {
        console.log("reconnection attempted")
        // attach the session ID to the next reconnection attempts
        socket.auth = {...socket.auth, sessionID };
        // store it in the localStorage
        localStorage.setItem("sessionID", sessionID);
        // save the ID of the user
        socket.userID = userID;
        
      });

      socket.on("connect", handleConnect)

      socket.on("disconnect", () => {
        const tempUsers = [...users]
        tempUsers.forEach((user) => {
          if (user.self) {
            user.connected = false
          }
        });
        console.log("tempUsers after disconnect" + tempUsers)
        setUsers(tempUsers)
      });

      socket.on("users", (usrs) => {
        const tempUsers = [...users]
        usrs.forEach((user) => {
          for (let i = 0; i <= tempUsers.length; i++) {
            const existingUser = tempUsers[i];
            if (existingUser && existingUser.userID === user.userID) {
              existingUser.connected = user.connected;
              setUsers(tempUsers)
              return;
            }
          }
          user.self = user.userID === socket.userID;
          initReactiveProperties(user);
          tempUsers.push(user);
        });
        tempUsers.sort((a, b) => {
          if (a.self) return -1;
          if (b.self) return 1;
          if (a.username < b.username) return -1;
          return a.username > b.username ? 1 : 0;
        });
        setUsers(tempUsers)
        // put the current user first, and sort by username
      });

    socket.on("user connected", (user) => {
      const tempUsers = [...users]
      for (let i = 0; i < tempUsers.length; i++) {
        const existingUser = tempUsers[i];
        if (existingUser.userID === user.userID) {
          existingUser.connected = true;
          setUsers(tempUsers)
          return;
        }
      }
      initReactiveProperties(user);
      tempUsers.push(user)
      console.log("tempUsers:" +  JSON.stringify(tempUsers))
      setUsers(tempUsers)
    });


    socket.on("user disconnected", (id) => {
      const tempUsers = [...users]
      for (let i = 0; i < tempUsers.length; i++) {
        const tempUser = tempUsers[i];
        if (tempUser.userID === id) {
          tempUser.connected = false;
          break;
        }
      }
      setUsers(tempUsers)
    });

    socket.on("private message", ({ content, from, to }) => {
      const tempUsers = [...users]
      for (let i = 0; i < tempUsers.length; i++) {

        const fromSelf = socket.userID === from;
        if (tempUsers[i].userID === (fromSelf ? to : from)) {
          tempUsers[i].messages.push({
            content,
            fromSelf,
          });
          if (tempUsers[i] !== selectedUser) {
            tempUsers[i].hasNewMessages = true;
          }
          break;
        }
      }
      setUsers(tempUsers)
    });
  }
  function cleanup() {
    socketIo.off("connect_error");
    socketIo.off("connect");
    socketIo.off("disconnect");
    socketIo.off("users");
    socketIo.off("user connected");
    socketIo.off("user disconnected");
    socketIo.off("private message");

}

return cleanup
  }, [socket])

  
    const initReactiveProperties = (user) => {
      user.messages = [];
      user.hasNewMessages = false;
    };

    function usernameInsideList(username, list) {
      for (let i = 0; i < list.length; i++) {
          if (list[i].username === username) {
              return true;
          }
      }
      return false;
    }

    function onSelectUser(user, idx) {
      console.log("User was selected")
        setSelectedUser(user);
        // user.hasNewMessages = false
        // selectedUser.current = user
        if (user.hasNewMessages) {
          let newArr = [...users];
          newArr[idx].hasNewMessages = false
          setUsers(newArr)
        }
    }

    function onMessage(content) {
      if (selectedUser) {
        socket.emit("private message", {
          content,
          to: selectedUser.userID,
        });
        const tempUser = {...selectedUser};
        tempUser.messages.push({
          content,
          fromSelf: true,
        });
        setSelectedUser(tempUser)
      }
    }

    function RightPanel() {
      if (selectedUser) {
        return ( 
        <MessagePanel
        user={selectedUser}
        onMessage={onMessage}
      />);
      } else {
        return (
          "Hello"
        )
      }
    }

    return (
      <div>
        <div className="left-panel">
          {users.map((user, id) => {
            return <User key={id} handleClick={onSelectUser} user={user}></User>;
          })}
        </div>
        <div className="right-panel">
          <RightPanel/>
        </div>
      </div>
    );
  }
import React,{useffect,useRef,useState}来自“React”;
从“/User”导入用户;
从“/MessagePanel”导入MessagePanel;
从“socket.io客户端”导入{io};
从“@/utils/socket”导入socketIo
函数useSocket(url、用户名){
const[socket,setSocket]=useState(null)
useffect(()=>{
const socketIo=io(url,{auth:{username},autoConnect:true});
设置插座(插座)
}, [])
返回插座
}
导出默认功能聊天(道具){
常量[selectedUser,setSelectedUser]=useState(null)
const[users,setUsers]=useState([])
const API_URL='1〕http://localhost:5000'
const socket=useSocket(API_URL,props.name)
useffect(()=>{
常量handleConnect=()=>{
日志(“用户已连接”)
const tempUsers=[…用户]
tempUsers.forEach((用户)=>{
if(user.self){
user.connected=true
}
});
设置用户(临时用户)
}
中频(插座){
const sessionID=localStorage.getItem(“sessionID”);
if(sessionID){
socket.auth={…socket.auth,sessionID};
//socket.connect();
}
socket.on(“session”,({sessionID,userID})=>{
console.log(“尝试重新连接”)
//将会话ID附加到下一次重新连接尝试
socket.auth={…socket.auth,sessionID};
//将其存储在localStorage中
setItem(“sessionID”,sessionID);
//保存用户的ID
socket.userID=userID;
});
插座打开(“连接”,手柄连接)
socket.on(“断开连接”),()=>{
const tempUsers=[…用户]
tempUsers.forEach((用户)=>{
if(user.self){
user.connected=false
}
});
console.log(“断开连接后的临时用户”+临时用户)
设置用户(临时用户)
});
socket.on(“用户”(usrs)=>{
const tempUsers=[…用户]
usrs.forEach((用户)=>{
for(设i=0;i{
如果(a.self)返回-1;
如果(b.self)返回1;
如果(a.usernameb.username?1:0;
});
设置用户(临时用户)
//将当前用户放在第一位,并按用户名排序
});
socket.on(“用户已连接”,(用户)=>{
const tempUsers=[…用户]
for(设i=0;i{
const tempUsers=[…用户]
for(设i=0;i{
const tempUsers=[…用户]
for(设i=0;i{
user.messages=[];
user.hasNewMessages=false;
};
函数usernameInsideList(用户名,列表){
for(设i=0;i{
返回;
})}
);
}
编辑:我通过进行以下编辑修复了最初的问题。但是,代码显然没有按预期工作


import React, { useEffect, useRef, useState } from "react";
import User from "./User";
import MessagePanel from "./MessagePanel";
import { io } from "socket.io-client";

export default function Chat(props) {

  const [selectedUser, setSelectedUser] = useState(null)
  const username = props.name;
  const [users, setUsers] = useState([])
  const API_URL='http://localhost:5000'
  const socket = useRef();

  useEffect(() => {
    socket.current = io(API_URL, { auth:{username}, autoConnect: true });
    
    const handleConnect = () => {
      const tempUsers = [...users]
      tempUsers.forEach((user) => {
        if (user.self) {
          user.connected = true
        }
      });
      setUsers(tempUsers)
    }

    if (socket.current) {
      const sessionID = localStorage.getItem("sessionID");

      if (sessionID) {
        socket.current.auth =  {...socket.current.auth, sessionID };
        // socket.connect();
      }

      socket.current.on("session", ({ sessionID, userID }) => {
        console.log("reconnection attempted")
        // attach the session ID to the next reconnection attempts
        socket.current.auth = {...socket.current.auth, sessionID };
        // store it in the localStorage
        localStorage.setItem("sessionID", sessionID);
        // save the ID of the user
        socket.current.userID = userID;
        
      });
      socket.current.on("connect", handleConnect)

      socket.current.on("disconnect", () => {
        const tempUsers = [...users]
        tempUsers.forEach((user) => {
          if (user.self) {
            user.connected = false
          }
        });
        console.log("tempUsers after disconnect" + tempUsers)
        setUsers(tempUsers)
      });

      socket.current.on("users", (usrs) => {
        const tempUsers = [...users]
        usrs.forEach((user) => {
          for (let i = 0; i <= tempUsers.length; i++) {
            const existingUser = tempUsers[i];
            if (existingUser && existingUser.userID === user.userID) {
              existingUser.connected = user.connected;
              setUsers(tempUsers)
              return;
            }
          }
          user.self = user.userID === socket.userID;
          initReactiveProperties(user);
          tempUsers.push(user);
        });
        setUsers(tempUsers)
        // put the current user first, and sort by username
      });

    socket.current.on("user connected", (user) => {
      const tempUsers = [...users]
      for (let i = 0; i < tempUsers.length; i++) {
        const existingUser = tempUsers[i];
        if (existingUser.userID === user.userID) {
          existingUser.connected = true;
          setUsers(tempUsers)
          return;
        }
      }
      initReactiveProperties(user);
      tempUsers.push(user)
      setUsers(tempUsers)
    });


    socket.current.on("user disconnected", (id) => {
      const tempUsers = [...users]
      for (let i = 0; i < tempUsers.length; i++) {
        const tempUser = tempUsers[i];
        if (tempUser.userID === id) {
          tempUser.connected = false;
          
          break;
        }
      }
      setUsers(tempUsers)
    });

    socket.current.on("private message", ({ content, from, to }) => {
      console.log("private message")
      const tempUsers = [...users]
      for (let i = 0; i < tempUsers.length; i++) {

        const fromSelf = socket.userID === from;
        if (tempUsers[i].userID === (fromSelf ? to : from)) {
          tempUsers[i].messages.push({
            content,
            fromSelf,
          });
          console.log("tempUser and selectedUser" + tempUser[i] + selectedUser)
          if (tempUsers[i] !== selectedUser) {
            tempUsers[i].hasNewMessages = true;
          }
          break;
        }
      }
      setUsers(tempUsers)
    });
  }
    function cleanup() {
      socket.current.off("connect_error");
      socket.current.off("connect");
      socket.current.off("disconnect");
      socket.current.off("users");
      socket.current.off("user connected");
      socket.current.off("user disconnected");
      socket.current.off("private message");
    }
    return cleanup
  }, [])

    //Use this to decrease DRY
    // const updateState = (state, setState, ...args) => {
    //   console.log(args)
    //   let newArr = [...state];
    //   newArr[idx].connected = true
    //   setState(newArr)
    // }

    const initReactiveProperties = (user) => {
      user.messages = [];
      user.hasNewMessages = false;
    };
    
    function usernameInsideList(username, list) {
      for (let i = 0; i < list.length; i++) {
          if (list[i].username === username) {
              return true;
          }
      }
      return false;
    }

    function onSelectUser(user, idx) {
        setSelectedUser(user);
        // selectedUser.current = user
        if (user.hasNewMessages) {
          let newArr = [...users];
          newArr[idx].hasNewMessages = false
          setUsers(newArr)
        }
    }
    function onMessage(content) {
      if (selectedUser) {
        socket.current.emit("private message", {
          content,
          to: selectedUser.userID,
        });
        const tempUser = {...selectedUser};

        tempUser.messages.push({
          content,
          fromSelf: true,
        });
        setSelectedUser(tempUser)
      }
    }
    function RightPanel() {
      if (selectedUser) {
        return ( 
        <MessagePanel
        user={selectedUser}
        onMessage={onMessage}
      />);
      } else {
        return (
          "Hello"
        )
      }
    }

    return (
      
      <div>

        <div className="left-panel">

          {users.map((user, id) => {
            return <User key={id} idx={id} handleClick={onSelectUser} user={user}></User>;
          })}
        </div>

        <div className="right-panel">
          <RightPanel/>
        </div>
      </div>
    );
  }

从“React”导入React,{useffect,useRef,useState};
从“/User”导入用户;
从“/MessagePanel”导入MessagePanel;
从“socket.io客户端”导入{io};
导出默认功能聊天(道具){
常数[选择]
<template>
  <div>
    <div class="left-panel">
      <user
        v-for="user in users"
        :key="user.userID"
        :user="user"
        :selected="selectedUser === user"
        @select="onSelectUser(user)"
      />
    </div>
    <message-panel
      v-if="selectedUser"
      :user="selectedUser"
      @input="onMessage"
      class="right-panel"
    />
  </div>
</template>

<script>
import socket from "../socket";
import User from "./User";
import MessagePanel from "./MessagePanel";

export default {
  name: "Chat",
  components: { User, MessagePanel },
  data() {
    return {
      selectedUser: null,
      users: [],
    };
  },
  methods: {
    onMessage(content) {
      if (this.selectedUser) {
        socket.emit("private message", {
          content,
          to: this.selectedUser.userID,
        });
        this.selectedUser.messages.push({
          content,
          fromSelf: true,
        });
      }
    },
    onSelectUser(user) {
      this.selectedUser = user;
      user.hasNewMessages = false;
    },
  },
  created() {
    socket.on("connect", () => {
      this.users.forEach((user) => {
        if (user.self) {
          user.connected = true;
        }
      });
    });

    socket.on("disconnect", () => {
      this.users.forEach((user) => {
        if (user.self) {
          user.connected = false;
        }
      });
    });

    const initReactiveProperties = (user) => {
      user.messages = [];
      user.hasNewMessages = false;
    };

    socket.on("users", (users) => {
      users.forEach((user) => {
        for (let i = 0; i < this.users.length; i++) {
          const existingUser = this.users[i];
          if (existingUser.userID === user.userID) {
            existingUser.connected = user.connected;
            return;
          }
        }
        user.self = user.userID === socket.userID;
        initReactiveProperties(user);
        this.users.push(user);
      });
      // put the current user first, and sort by username
      this.users.sort((a, b) => {
        if (a.self) return -1;
        if (b.self) return 1;
        if (a.username < b.username) return -1;
        return a.username > b.username ? 1 : 0;
      });
    });

    socket.on("user connected", (user) => {
      for (let i = 0; i < this.users.length; i++) {
        const existingUser = this.users[i];
        if (existingUser.userID === user.userID) {
          existingUser.connected = true;
          return;
        }
      }
      initReactiveProperties(user);
      this.users.push(user);
    });

    socket.on("user disconnected", (id) => {
      for (let i = 0; i < this.users.length; i++) {
        const user = this.users[i];
        if (user.userID === id) {
          user.connected = false;
          break;
        }
      }
    });

    socket.on("private message", ({ content, from, to }) => {
      for (let i = 0; i < this.users.length; i++) {
        const user = this.users[i];
        const fromSelf = socket.userID === from;
        if (user.userID === (fromSelf ? to : from)) {
          user.messages.push({
            content,
            fromSelf,
          });
          if (user !== this.selectedUser) {
            user.hasNewMessages = true;
          }
          break;
        }
      }
    });
  },
  destroyed() {
    // socket.off("connect");
    // socket.off("disconnect");
    // socket.off("users");
    // socket.off("user connected");
    // socket.off("user disconnected");
    // socket.off("private message");
  },
};
</script>

<style scoped>
.left-panel {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  width: 260px;
  overflow-x: hidden;
  background-color: #3f0e40;
  color: white;
}

.right-panel {
  margin-left: 260px;
}
</style>