🌐 Detecting your location…

So verwenden Sie WebSockets in React mit Socket.io im Jahr 2026: Vollständige Anleitung

⏱️5 min read  ·  956 words

Echtzeitfunktionen – Live-Chat, Benachrichtigungen, gemeinsame Bearbeitung, Live-Dashboards – erfordern eine dauerhafte Verbindung. In ReactSocket.io ist die praktischste Möglichkeit, WebSocket-basierte Echtzeitfunktionen hinzuzufügen. Diese Anleitung zeigt, wie man es sauber mit React-Hooks integriert.

Einrichtung

npm install socket.io-client

Grundlegende Verbindung

// socket.js - create a single shared socket instance
import { io } from 'socket.io-client';

export const socket = io('http://localhost:3001', {
  autoConnect: false,   // connect manually when ready
  reconnection: true,
  reconnectionDelay: 1000,
});

Ein wiederverwendbarer Steckdosenhaken

// hooks/useSocket.js
import { useEffect, useState } from 'react';
import { socket } from '../socket';

export function useSocket() {
  const [isConnected, setIsConnected] = useState(socket.connected);

  useEffect(() => {
    socket.connect();

    function onConnect() { setIsConnected(true); }
    function onDisconnect() { setIsConnected(false); }

    socket.on('connect', onConnect);
    socket.on('disconnect', onDisconnect);

    // Cleanup - CRITICAL to prevent duplicate listeners
    return () => {
      socket.off('connect', onConnect);
      socket.off('disconnect', onDisconnect);
      socket.disconnect();
    };
  }, []);

  return { socket, isConnected };
}

Auf Ereignisse achten

// hooks/useMessages.js - subscribe to a specific event
import { useEffect, useState } from 'react';
import { socket } from '../socket';

export function useMessages() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    function onMessage(msg) {
      setMessages(prev => [...prev, msg]);
    }

    socket.on('message', onMessage);

    // Always clean up the listener to avoid duplicates on re-render
    return () => {
      socket.off('message', onMessage);
    };
  }, []);

  const sendMessage = (text) => {
    socket.emit('send_message', { text, timestamp: Date.now() });
  };

  return { messages, sendMessage };
}

Eine vollständige Chat-Komponente

import { useState } from 'react';
import { useSocket } from './hooks/useSocket';
import { useMessages } from './hooks/useMessages';

function Chat() {
  const { isConnected } = useSocket();
  const { messages, sendMessage } = useMessages();
  const [input, setInput] = useState('');

  const handleSend = (e) => {
    e.preventDefault();
    if (input.trim()) {
      sendMessage(input);
      setInput('');
    }
  };

  return (
    <div>
      <div>Status: {isConnected ? 'Connected' : 'Disconnected'}</div>
      <ul>
        {messages.map((msg, i) => (
          <li key={i}>{msg.text}</li>
        ))}
      </ul>
      <form onSubmit={handleSend}>
        <input value={input} onChange={e => setInput(e.target.value)} />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}

Tippindikatoren und Präsenz

export function useTyping() {
  const [typingUsers, setTypingUsers] = useState([]);

  useEffect(() => {
    function onTyping({ user, isTyping }) {
      setTypingUsers(prev =>
        isTyping
          ? [...new Set([...prev, user])]
          : prev.filter(u => u !== user)
      );
    }
    socket.on('user_typing', onTyping);
    return () => socket.off('user_typing', onTyping);
  }, []);

  const setTyping = (isTyping) => {
    socket.emit('typing', { isTyping });
  };

  return { typingUsers, setTyping };
}

Handhabung der Wiederverbindung

useEffect(() => {
  function onReconnect() {
    console.log('Reconnected - re-syncing state');
    // Re-fetch missed data or re-join rooms after reconnection
    socket.emit('rejoin_room', { roomId });
  }

  socket.io.on('reconnect', onReconnect);
  return () => socket.io.off('reconnect', onReconnect);
}, [roomId]);
// Socket.io auto-reconnects; use this hook to re-sync after connection drops

Die entscheidende Regel: Hörer immer bereinigen

Der häufigste Socket.io + React-Fehler sind doppelte Event-Handler. Jedes Mal, wenn eine Komponente erneut gerendert oder bereitgestellt wird und Sie einen Listener hinzufügen, ohne den alten zu entfernen, sammeln sich Duplikate an – eine einzelne Nachricht löst Ihren Handler mehrmals aus. Geben Sie immer eine Bereinigungsfunktion von useEffect zurück, die den Listener mitsocket.off()entfernt . Dies ist für korrektes Verhalten nicht verhandelbar.

Authentifizierung

// Pass auth token when connecting
export const socket = io('http://localhost:3001', {
  auth: {
    token: localStorage.getItem('accessToken'),
  },
  autoConnect: false,
});

// Server verifies the token in a middleware before allowing the connection
// Update the token if it changes:
socket.auth.token = newToken;
socket.disconnect().connect();   // reconnect with new auth

Häufig gestellte Fragen

F: Warum erhalte ich doppelte Nachrichten?
A: Sie fügen Ereignis-Listener hinzu, ohne sie zu bereinigen. Bei jedem erneuten Rendern wird ein weiterer Listener hinzugefügt. Geben Sie immer eine Bereinigungsfunktion von useEffect zurück, diesocket.off()aufruft um den Listener zu entfernen. Dies ist der häufigste Socket.io + React-Fehler.

F: Soll ich den Socket innerhalb oder außerhalb der Komponente erstellen?
A: Außerhalb – erstellen Sie eine einzelne gemeinsam genutzte Socket-Instanz in einem separaten Modul (socket.js) und importieren Sie sie. Wenn Sie es innerhalb einer Komponente erstellen, entsteht bei jedem Rendern eine neue Verbindung. Eine gemeinsame Instanz ist das richtige Muster.

F: Wie gehe ich mit dem Socket in mehreren Komponenten um?
A: Importieren Sie die Shared-Socket-Instanz in jede Komponente, die sie benötigt, oder verwenden Sie einen Kontextanbieter, um den Verbindungsstatus freizugeben. Jede Komponente abonniert die Ereignisse, die sie benötigt (mit Bereinigung), über ihren eigenen useEffect. Der einzelne Socket verarbeitet sie alle.

F: Socket.io oder natives WebSocket?
A: Socket.io für Produktions-React-Apps – es fügt automatische Wiederverbindung, Fallback auf Long-Polling, Räume und eine ereignisbasierte API hinzu, die viel Arbeit spart. Native WebSocket ist eine niedrigere Ebene und erfordert, dass Sie die Wiederverbindung und die Ereignisbehandlung selbst erstellen.

F: Wie teste ich Echtzeitfunktionen?
A: Öffnen Sie die App in mehreren Browser-Registerkarten oder -Fenstern, um mehrere Benutzer zu simulieren und die Verbreitung von Nachrichten/Ereignissen zu überprüfen. Für automatisierte Tests simulieren Sie den Socket oder verwenden Sie einen Test-Socket.io-Server. Manuelle Multi-Tab-Tests sind der schnellste Weg, um zu überprüfen, ob das Verhalten in Echtzeit funktioniert.

Fazit

Das Hinzufügen von Echtzeitfunktionen zu React mit Socket.io ist mit den richtigen Mustern unkompliziert:Erstellen Sie eine einzelne gemeinsam genutzte Socket-Instanz außerhalb von Komponenten, wickeln Sie die Verbindung und die Ereignisbehandlung in benutzerdefinierte Hooks ein und bereinigen Sie IMMER Listener in der Rückgabefunktion von useEffect. Das benutzerdefinierte Hook-Muster (useSocket, useMessages, useTyping) sorgt dafür, dass Ihre Echtzeitlogik organisiert und wiederverwendbar bleibt. Bewältigen Sie die erneute Verbindung, indem Sie den Status nach der Wiederherstellung der Verbindung erneut synchronisieren, und übergeben Sie Authentifizierungstoken bei der Verbindung für gesicherte Sockets. Die wichtigste Regel besteht darin, die Listener mitsocket.off()zu bereinigen – Das Vergessen führt zu doppelten Handlern und ist der häufigste Socket.io + React-Fehler. Mit diesen Mustern können Sie Chats, Benachrichtigungen, Live-Dashboards und Funktionen für die Zusammenarbeit sauber in React erstellen.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা