Day 03 Applied Skills

Streaming Chat Responses — React + AI

Make your React AI chat stream responses word by word using the Claude streaming API. Server-sent events and real-time UI updates.

~1 hour Hands-on Precision AI Academy

Today's Objective

Claude's responses often include markdown — bold, code blocks, lists.

01

How Streaming Works

Instead of waiting for the complete response, the server streams tokens as they're generated. The browser receives a stream of server-sent events (SSE) and updates the UI incrementally.

The flow: user sends message → server starts streaming Claude's response → browser receives chunks → React appends each chunk to the message in state → full response appears token by token.

02

Server-Side Streaming

javascript — server.js
javascript — server.js
app.post('/api/chat/stream', async (req, res) => {
  const { messages } = req.body;

  // Set SSE headers
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  try {
    const stream = client.messages.stream({
      model: 'claude-3-haiku-20240307',
      max_tokens: 1024,
      messages: messages,
    });

    // Send each text delta as an SSE event
    stream.on('text', (text) => {
      res.write(`data: ${JSON.stringify({ text })}\n\n`);
    });

    stream.on('end', () => {
      res.write('data: [DONE]\n\n');
      res.end();
    });

    stream.on('error', (err) => {
      res.write(`data: ${JSON.stringify({ error: err.message })}\n\n`);
      res.end();
    });
  } catch (err) {
    res.write(`data: ${JSON.stringify({ error: err.message })}\n\n`);
    res.end();
  }
});
03

Reading the Stream in React

jsx
jsx
async function sendMessageStream(userText) {
  const userMsg = { id: Date.now(), role: 'user', content: userText };
  setMessages(prev => [...prev, userMsg]);
  setIsLoading(true);

  // Add a placeholder for the streaming response
  const aiId = Date.now() + 1;
  setMessages(prev => [...prev, { id: aiId, role: 'assistant', content: '' }]);

  try {
    const response = await fetch('/api/chat/stream', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ messages: [...messages, userMsg] })
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      const chunk = decoder.decode(value);
      const lines = chunk.split('\n').filter(l => l.startsWith('data: '));

      for (const line of lines) {
        const data = line.slice(6); // remove "data: "
        if (data === '[DONE]') break;

        try {
          const { text } = JSON.parse(data);
          if (text) {
            // Append the chunk to the last message
            setMessages(prev =>
              prev.map(msg =>
                msg.id === aiId
                  ? { ...msg, content: msg.content + text }
                  : msg
              )
            );
          }
        } catch {}
      }
    }
  } finally {
    setIsLoading(false);
  }
}
💡
The key pattern: Create the assistant message with empty content before the stream starts. Then append each chunk to it. This gives React something to update rather than inserting a new message on every chunk.
04

Auto-Scroll to Latest Message

jsx
jsx
import { useRef, useEffect } from 'react';

function ChatMessages({ messages, isLoading }) {
  const bottomRef = useRef(null);

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

  return (
    
{messages.map(msg => )} {isLoading && }
{/* invisible element at the bottom */}
); }
05

Markdown Rendering

Claude's responses often include markdown — bold, code blocks, lists. Render it properly:

bash
bash
npm install react-markdown
jsx
jsx
import ReactMarkdown from 'react-markdown';

function MessageCard({ role, content }) {
  return (
    
{role === 'assistant' ? {content} :

{content}

}
); }

Supporting References & Reading

Go deeper with these external resources.

Docs
Streaming: Responses That Appear Word by Word Official documentation for react ai.
GitHub
Streaming: Responses That Appear Word by Word Open source examples and projects for Streaming: Responses That Appear Word by Word
MDN
MDN Web Docs Comprehensive web technology reference

Day 3 Checkpoint

Before moving on, confirm understanding of these key concepts:

Continue To Day 4
Day 4 of the React + AI in 5 Days course