useEffect 中的套接字连接事件在创建组件时不起作用,但在 React 中刷新页面后起作用

socket connect event inside useEffect does not work when component is created but works after refreshing the page in React

我想将单个套接字实例传递给我的所有反应组件,因此我在 App.js 的 useEffect 内连接一个套接字,它包含所有组件,并将我的侦听器保留在导航栏组件的 useEffect 内。 当第一次打开应用程序时,useEffect 被触发但套接字未连接 time.But 当我刷新页面时,套接字已连接并轻松传递到我想要的组件。

App.js

function App() {

  const authCtx = useContext(AuthContext)
  const username = authCtx.username
  const [socket, setSocket] = useState(null);

  const [user, setUser] = useState("");

  useEffect(() => {
    setSocket(io("http://localhost:7000"));

  }, []);

  useEffect(() => {
    socket?.emit("join_room",{
            chatroom:username
            });
      
  }, [socket, user]);

  return (
    <div>

      {authCtx.isLoggedIn && socket && <MainNavigation socket={socket} />}
      {authCtx.isLoggedIn && <FloatingBtn/>}
      <Switch>
        {authCtx.isLoggedIn && socket && <Route exact path='/Chat'>
          <Chat socket={socket} />
        </Route>}   
        
      </Switch>
    </div>
  );
}

export default App;

请注意,在 useEffect 中,依赖项是 authContext.username,而不是用户。

useEffect(() => {
    if(authCtx.username && socket){
        socket?.emit("join_room", {
          chatroom: authCtx.username
        });
    }
  }, [socket, authCtx.username]);

要拥有一个全局套接字实例,您可以创建一个 SocketContext,例如:

import { createContext, useContext } from "react";

const SocketContext = createContext({
  socket: undefined
});
export const SocketProvider = ({ childern }) => {
  const authCtx = useContext(AuthContext);

  const [socket, setSocket] = useState(null);

  useEffect(() => {
    setSocket(io("http://localhost:7000"));
  }, []);

  useEffect(() => {

    if(authCtx.username && socket){
        socket?.emit("join_room", {
          chatroom: authCtx.username
        });
    }

  }, [socket, authCtx.username]);
  return (
    <SocketContext.Provider value={{ socket }}>
      {childern}
    </SocketContext.Provider>
  );
};

export default SocketContext;

在您的 index.js 中定义它:

import ReactDOM from "react-dom";
import { SocketProvider } from "../SocketContext";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <AuthProvider>
    <SocketProvider>
      <App />
    </SocketProvider>
  </AuthProvider>,
  rootElement
);

并在每个组件中使用它,例如:

import React, { useContext } from "react";
import SocketContext from "../SocketContext";

const RandomComponent = () => {
  const { socket } = useContext(SocketContext);

  React.useEffect(() => {
    console.log(socket);
  }, [socket]);
  return <div></div>;
};

没有将其作为道具传递。