React Academy · leksjon

Bygge en chatkomponent i sanntid

Vis meldinger i sanntid i en scrollbar chatliste ved hjelp av WebSocket-events og React-state.

Leksjon 3 av 414 trinn

Bygge en chatkomponent i sanntid er en gratis leksjon i React Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i React Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i React Academy inneholder totalt 4 leksjoner.

Arkitektur for chat-komponenten

En sanntidschat har tre deler: en meldingsliste (visning), et meldingsfelt (sending) og et WebSocket-/Socket.IO-tilkoblingslag. Hold socket-logikken i en egen hook.

Meldingsdatastruktur

Definer et TypeScript-grensesnitt for chatmeldinger, slik at komponenten beholder typesikkerheten gjennomgående.

interface Message {
  id: string;
  text: string;
  sender: string;
  timestamp: number;
}

const [messages, setMessages] = useState<Message[]>([]);

useChat-hook

Samle tilkoblingen, meldingstilstanden og sendefunksjonen i én hook.

function useChat(roomId: string) {
  const [messages, setMessages] = useState<Message[]>([]);

  useEffect(() => {
    socket.connect();
    socket.emit('join-room', roomId);
    socket.on('message', (msg: Message) => setMessages(m => [...m, msg]));
    return () => {
      socket.off('message');
      socket.emit('leave-room', roomId);
      socket.disconnect();
    };
  }, [roomId]);

  const sendMessage = useCallback((text: string) => {
    const msg: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
    socket.emit('message', msg);
  }, []);

  return { messages, sendMessage };
}

Meldingslistekomponent

Rendrer meldinger i en liste med rulling. Bruk useRef på sentinel-elementet nederst, og rull dit når nye meldinger kommer inn.

function MessageList({ messages }: { messages: Message[] }) {
  const bottomRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  return (
    <div className="message-list">
      {messages.map(msg => (
        <div key={msg.id} className={`msg ${msg.sender === 'me' ? 'mine' : 'theirs'}`}>
          <span>{msg.sender}</span>
          <p>{msg.text}</p>
        </div>
      ))}
      <div ref={bottomRef} />
    </div>
  );
}

Komponent for meldingsfelt

Et kontrollert inndatafelt som sender ved Enter eller knappetrykk. Tøm feltet etter sending.

function MessageInput({ onSend }: { onSend: (text: string) => void }) {
  const [text, setText] = useState('');

  const handleSend = () => {
    if (!text.trim()) return;
    onSend(text.trim());
    setText('');
  };

  return (
    <div className="input-row">
      <input
        value={text}
        onChange={e => setText(e.target.value)}
        onKeyDown={e => e.key === 'Enter' && handleSend()}
        placeholder="Type a message..."
      />
      <button onClick={handleSend}>Send</button>
    </div>
  );
}

Sette sammen chatgrensesnittet

Sett sammen hooken og underkomponentene til en ChatRoom-komponent.

function ChatRoom({ roomId }: { roomId: string }) {
  const { messages, sendMessage } = useChat(roomId);

  return (
    <div className="chat-room">
      <h2>Room: {roomId}</h2>
      <MessageList messages={messages} />
      <MessageInput onSend={sendMessage} />
    </div>
  );
}

Optimistiske oppdateringer

Legg meldingen til i lokal state umiddelbart, før serveren bekrefter den, slik at brukeren får umiddelbar tilbakemelding. Synkroniser eller fjern meldingen hvis serveren returnerer en feil.

const sendMessage = useCallback((text: string) => {
  const optimistic: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
  setMessages(m => [...m, optimistic]); // instant feedback
  socket.emit('message', optimistic, (err) => {
    if (err) setMessages(m => m.filter(msg => msg.id !== optimistic.id));
  });
}, []);

Skriveindikatorer

Send ut en typing-hendelse ved endringer i inndata (med debounce), og lytt etter andres skrivehendelser for å vise en indikator.

const emitTyping = useMemo(() => debounce(() => socket.emit('typing'), 300), []);

useEffect(() => {
  socket.on('user-typing', (user) => setTypingUser(user));
  return () => socket.off('user-typing');
}, []);

Tidsstempler for meldinger

Formater tidsstempler med Intl.DateTimeFormat for lokalitetstilpasset visning.

function formatTime(ts: number) {
  return new Intl.DateTimeFormat('en', { hour: '2-digit', minute: '2-digit' }).format(ts);
}

<span className="timestamp">{formatTime(msg.timestamp)}</span>

Lesebekreftelser

Send ut en read-hendelse når brukeren ser på meldinger, og lytt etter lesebekreftelser fra serveren for å vise avkrysningsmerker.

Virtualisert meldingsliste

For lange chathistorikker kan du bruke react-window eller react-virtual til å virtualisere meldingslisten og bare rendre synlige rader.

Begrense meldingshistorikken

Begrens meldingsarrayet i state for å hindre ubegrenset minnevekst i lange økter.

socket.on('message', (msg: Message) => {
  setMessages(prev => [...prev.slice(-499), msg]); // keep last 500
});

Kort sjekk

Hva er hensikten med å rulle til sentinel-div-elementet nederst når nye meldinger kommer inn i en chatliste?

Oppsummering

Bygg en sanntidschat med en useChat-hook som samler socket-logikken, en MessageList med automatisk rulling og en MessageInput som tømmes ved sending. Bruk optimistiske oppdateringer for umiddelbar tilbakemelding, og begrens meldingshistorikken for å unngå minnelekkasjer.

Gratis å komme i gang

Lær deg React med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
88
Leksjoner
324

Ofte stilte spørsmål

Er leksjonen «Bygge en chatkomponent i sanntid» gratis?

Ja – hele teksten i «Bygge en chatkomponent i sanntid» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av React Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i React Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Bygge en chatkomponent i sanntid»?

Vis meldinger i sanntid i en scrollbar chatliste ved hjelp av WebSocket-events og React-state. Du øver på React Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med React Academy?

Ingen tidligere erfaring er nødvendig. React Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Bygge en chatkomponent i sanntid»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne React Academy-leksjonen?

Ja. Alle React Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Grunnleggende om WebSocket i nettleseren
  2. Bruke Socket.IO med React
  3. Bygge en chatkomponent i sanntid
  4. Gjenoppretting av tilkobling, feilhåndtering og opprydding
← Tilbake til React Academy