0Pricing
React Academy · Lesson

Reconnection, Error Handling & Cleanup

Handle disconnections gracefully and clean up socket listeners in useEffect.

Reconnection, Error Handling & Cleanup is a free React Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Reconnection Matters

Network interruptions are common on mobile. Without reconnection logic, users silently lose their real-time connection. A good strategy retries automatically with backoff.

Socket.IO Auto-Reconnect

Socket.IO reconnects automatically by default. Configure reconnectionAttempts, reconnectionDelay, and reconnectionDelayMax in the io() options.

const socket = io('https://api.example.com', {
  reconnectionAttempts: 5,
  reconnectionDelay: 1000,       // initial delay
  reconnectionDelayMax: 10000,   // max delay (exponential backoff)
  randomizationFactor: 0.5,
});

Tracking Connection State in React

Listen to connect, disconnect, and connect_error events and reflect the status in component state.

function useConnectionStatus() {
  const [status, setStatus] = useState<'connected' | 'disconnected' | 'error'>(
    socket.connected ? 'connected' : 'disconnected'
  );

  useEffect(() => {
    socket.on('connect', () => setStatus('connected'));
    socket.on('disconnect', () => setStatus('disconnected'));
    socket.on('connect_error', () => setStatus('error'));
    return () => {
      socket.off('connect');
      socket.off('disconnect');
      socket.off('connect_error');
    };
  }, []);

  return status;
}

Showing a Reconnection Banner

Display a banner when the socket disconnects so users know they're offline and reconnection is in progress.

function ConnectionBanner() {
  const status = useConnectionStatus();
  if (status === 'connected') return null;
  return (
    <div className="banner warning">
      {status === 'error' ? 'Connection failed' : 'Reconnecting...'}
    </div>
  );
}

Manual Reconnection

After exhausting retries, let users trigger a manual reconnect via a button.

const [failed, setFailed] = useState(false);

socket.on('reconnect_failed', () => setFailed(true));

if (failed) {
  return (
    <button onClick={() => { setFailed(false); socket.connect(); }}>
      Retry connection
    </button>
  );
}

Raw WebSocket Reconnection

Raw WebSocket has no built-in reconnect. Implement exponential backoff manually: on close, wait Math.min(delay * 2, maxDelay) before attempting a new connection.

function connectWithBackoff(url, attempt = 0) {
  const ws = new WebSocket(url);
  ws.onclose = () => {
    const delay = Math.min(1000 * 2 ** attempt, 30000);
    setTimeout(() => connectWithBackoff(url, attempt + 1), delay);
  };
  return ws;
}

Cleanup in useEffect

Every socket listener added in a useEffect must be removed in the cleanup function. Failing to do so causes memory leaks and duplicate event handling.

useEffect(() => {
  const onData = (d) => setState(d);
  socket.on('data', onData);

  return () => {
    socket.off('data', onData); // remove specific handler reference
  };
}, []);

Avoiding Stale Closures in Handlers

When a socket handler references state or props, it captures a stale closure. Use a ref to always access the latest value.

const handlerRef = useRef(null);
handlerRef.current = (msg) => updateMessages(messages, msg); // fresh ref each render

useEffect(() => {
  const onMsg = (...args) => handlerRef.current(...args);
  socket.on('message', onMsg);
  return () => socket.off('message', onMsg);
}, []); // no deps needed

Flushing Pending Messages on Reconnect

Queue outgoing messages while disconnected and flush the queue when the connection re-establishes.

const queue = useRef<string[]>([]);

socket.on('connect', () => {
  while (queue.current.length) {
    socket.emit('message', queue.current.shift());
  }
});

function send(text: string) {
  if (socket.connected) socket.emit('message', text);
  else queue.current.push(text);
}

Rejoining Rooms After Reconnect

Socket.IO clears room memberships on disconnect. Rejoin rooms when the socket reconnects to restore subscriptions.

useEffect(() => {
  function rejoin() { socket.emit('join-room', roomId); }
  socket.on('connect', rejoin);
  return () => socket.off('connect', rejoin);
}, [roomId]);

Global Error Handling

Handle unrecoverable errors gracefully: show an error UI and offer a page reload as the last resort.

socket.on('connect_error', (err) => {
  console.error('Socket error:', err.message);
  // Show user-friendly error
});

Quick Check

What is the risk of not removing a socket event listener in useEffect cleanup?

Recap

Configure Socket.IO reconnection with backoff options. Reflect connection status in React state, show a reconnection banner, rejoin rooms after reconnect, and always remove listeners in useEffect cleanup. Queue pending messages while offline and flush on reconnect.

Frequently asked questions

Is the “Reconnection, Error Handling & Cleanup” lesson free?

Yes — the full text of “Reconnection, Error Handling & Cleanup” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Reconnection, Error Handling & Cleanup”?

Handle disconnections gracefully and clean up socket listeners in useEffect. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Reconnection, Error Handling & Cleanup” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. WebSocket Fundamentals in the Browser
  2. Using Socket.IO with React
  3. Building a Real-Time Chat Component
  4. Reconnection, Error Handling & Cleanup
← Back to React Academy