I have a component called NAV this component is static in the application, in that component I handle the socket.on listener to store the notification information, if there is a path that does not contain the socket it works normal, but when I put the socket in a component Inside of a route in react, the socket that was inside the NAV component stops working, I swear I must repeat the socket.on code of the NAV component so that the information can arrive again, this is a bad practice because the code should not be repeated so much This happens to me with 5 components in different routes, but I don't know how to prevent this from happening
I tried to make a component that covers all the components inside the routes and manages the sockets information there but it didn't work for me.
THIS IS THE CODE I HAVE IN THE SOCKET ON THE SERVER
socket.on("received event", async (id, productID) => {
if (id || productID) {
let product;
if (productID !== undefined)
product = await Product.findById(productID);
const user = getUser(id ? id : product.owner);
if (user.length > 0)
user.map((user) => io.to(user.socketId).emit("received event"));
}
});
THIS IS THE CODE THAT I HAVE IN THE NAV BUT I HAVE TO REPEAT IT IN EACH ROUTE THAT INTEGRATES THE SOCKET
useEffect(() => {
socket.on("received event", async () => {
await searchNotifications();
});
return () => socket.off();
});
THIS IS THE MAIN APP COMPONENT
function App() {
return (
<LoadingZone>
<Nav /> // HERE IS THE "SOCKET" THE ABOVE CODE THAT IS REPEATED
<Routes>
<Route path="/" element={<Home />}/>
<Route path="/report" element={<PrivateRoute><Report /></PrivateRoute>}/>
<Route path="/messages" element={<PrivateRoute><Messages /></PrivateRoute>}/>
<Route path="/notifications" element={<PrivateRoute><Notifications /></PrivateRoute>}/>
<Route path="/help/*" element={<Help />} />
<Route path="/post/information/*" element={<Post />} /> // THE SOCKET THAT IS IN THE NAV DOES NOT AFFECT IT
</Routes>
<Footer />
<PopupWindow/>
</LoadingZone>
);
}
export default App;
It's supposed to keep taking the socket from the NAV since it doesn't depend on any route but it doesn't, I have the main socket in a separate file where I can access the different components. But this is my problem
It's supposed to keep taking the socket from the NAV since it doesn't depend on any route but it doesn't
CodePudding user response:
Not a lot of context provided for what exactly isn't working, but it appears the useEffect
hook is missing a dependency array. Without it the component(s) are constantly opening/closing (subscribing/unsubscribing) the socket connection.
Since it doesn't appear there are any external dependencies try adding an empty dependency array so the effect is run once when the component mounts to connect the socket event, and unsubscribed from the event when the component unmounts.
Example:
useEffect(() => {
socket.on("received event", async () => {
await searchNotifications();
});
return () => socket.off();
}, []); // <-- add empty dependency array
CodePudding user response:
You can create global hooks to handle repeated useEffect in many components. For example like this:
export const useSocket = () => {
const [data, setData] = useState();
useEffect(() => {
socket.on("received event", async () => {
const res = await searchNotifications();
setData(res);
});
return () => socket.off();
});
return data;
}
And in any component that needs to use socket:
import { useSocket } from 'yourJsFile';
const AnyComponent = props => {
const data = useSocket();
}