I'm debugging a React 18 application that establishes a WebSocket connection inside a custom hook.
function useSocket(url) {
useEffect(() => {
const socket = new WebSocket(url);
socket.onopen = () => {
console.log("Connected");
};
return () => {
socket.close();
console.log("Closed");
};
}, [url]);
}
The component using this hook is wrapped in .
In development mode I see:
Connected
Closed
Connected
This causes issues because my backend briefly registers two connections and triggers duplicate subscription events.
I understand that React intentionally invokes effects twice in development, but I'm trying to understand the recommended pattern for WebSocket connections, SSE streams, or third-party SDK initialization.
Questions:
Is React's double invocation guaranteed to always call cleanup before the second mount?
Should external resources like WebSockets be initialized outside React effects?
How do production-grade applications prevent duplicate side effects while still keeping StrictMode enabled?
Is there an official React-recommended pattern for long-lived connections?
I'm looking for guidance beyond simply disabling StrictMode.