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>;
};
没有将其作为道具传递。
我想将单个套接字实例传递给我的所有反应组件,因此我在 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>;
};
没有将其作为道具传递。