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

Posted

技术标签:

【中文标题】useEffect 中的套接字连接事件在创建组件时不起作用,但在 React 中刷新页面后起作用【英文标题】:socket connect event inside useEffect does not work when component is created but works after refreshing the page in React 【发布时间】:2022-01-05 14:37:38 【问题描述】:

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

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;

【问题讨论】:

【参考方案1】:

请注意,在 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>;
;

不将其作为道具传递。

【讨论】:

不知道如何感谢您。 :)

以上是关于useEffect 中的套接字连接事件在创建组件时不起作用,但在 React 中刷新页面后起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在Angular中的事件函数内调用组件的方法?

在哪里使用 React 中的 Hooks 定义需要来自全局状态的数据的套接字事件侦听器

如何在 UseEffect 中将事件侦听器添加到 UseRefs

手动刷新页面时如何强制app.js中的useEffect在其他组件的useEffect之前加载

UseEffect 中的 UseRef 问题

next.js socket.io 使用效果不更新套接字消息