TokenMix Research Lab · 2026-04-13

AI API for React Apps: How to Add AI to React with Streaming, useChat Hook, and Provider Comparison (2026)
Adding an AI API to a React app requires three things: a backend proxy to protect your API key, a streaming connection for real-time responses, and a display component that renders tokens as they arrive. This guide covers every approach -- plain fetch, the Vercel AI SDK useChat hook, and direct provider SDKs -- with working code for each. We compare OpenAI, Anthropic, Google, and DeepSeek for React integration, covering cost, latency, and developer experience. All data tracked by TokenMix.ai as of April 2026.
Table of Contents
- [Quick Comparison: React AI Integration Approaches]
- [Architecture: Why You Need a Backend Proxy]
- [Method 1: Fetch API with Streaming Display]
- [Method 2: Vercel AI SDK useChat Hook]
- [Method 3: Direct Provider SDKs]
- [AI Provider Comparison for React Apps]
- [Building a Streaming Chat Component]
- [Cost Estimation for React AI Features]
- [How to Choose Your React AI Stack]
- [Production Best Practices]
- [Conclusion]
- [FAQ]
Quick Comparison: React AI Integration Approaches
| Approach | Setup Time | Streaming | Provider Flexibility | Best For |
|---|---|---|---|---|
| Fetch API | 20 min | Manual SSE parsing | Any provider | Simple integrations, full control |
| Vercel AI SDK (useChat) | 10 min | Built-in | OpenAI, Anthropic, Google, Mistral | Chat UIs, rapid prototyping |
| Provider SDK (OpenAI) | 15 min | SDK-managed | Single provider | OpenAI-specific features |
| Provider SDK (Anthropic) | 15 min | SDK-managed | Single provider | Claude-specific features |
| TokenMix.ai API | 10 min | OpenAI-compatible | 300+ models | Multi-provider, cost optimization |
Architecture: Why You Need a Backend Proxy
Never call AI APIs directly from React client code. Your API key would be visible in browser developer tools, network requests, and your JavaScript bundle.
The correct architecture:
React Client → Your Backend (API key stored here) → AI Provider API
Your backend can be:
- An Express/Fastify server
- A Next.js API route
- A Cloudflare Worker
- A Vercel Edge Function
- A simple Node.js server
The backend does three things:
- Receives the user's message from your React app
- Attaches the API key and sends the request to the AI provider
- Streams the response back to React
This pattern keeps your API key secure and lets you add rate limiting, logging, and cost controls on the backend.
For developers who want to skip building a custom backend, TokenMix.ai provides a managed proxy with built-in rate limiting, cost tracking, and multi-provider routing.
Method 1: Fetch API with Streaming Display
The fetch API approach gives you full control with zero dependencies. It works with any React setup and any AI provider.
Backend (Express example):
import express from 'express';
import OpenAI from 'openai';
const app = express();
app.use(express.json());
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
app.post('/api/chat', async (req, res) => {
const { messages } = req.body;
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const stream = await client.chat.completions.create({
model: 'gpt-4.1-mini',
messages,
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
res.write(`data: ${JSON.stringify({ content })}\n\n`);
}
}
res.write('data: [DONE]\n\n');
res.end();
});
React component with streaming:
import { useState, useCallback } from 'react';
function ChatApp() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [isStreaming, setIsStreaming] = useState(false);
const sendMessage = useCallback(async () => {
const userMessage = { role: 'user', content: input };
const updatedMessages = [...messages, userMessage];
setMessages(updatedMessages);
setInput('');
setIsStreaming(true);
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: updatedMessages }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let assistantMessage = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
const lines = text.split('\n').filter(line => line.startsWith('data: '));
for (const line of lines) {
const data = line.slice(6);
if (data === '[DONE]') break;
const parsed = JSON.parse(data);
assistantMessage += parsed.content;
setMessages([...updatedMessages, { role: 'assistant', content: assistantMessage }]);
}
}
setIsStreaming(false);
}, [messages, input]);
return (
<div>
{messages.map((m, i) => (
<div key={i} className={m.role}>{m.content}</div>
))}
<input value={input} onChange={e => setInput(e.target.value)}
onKeyDown={e => e.key === 'Enter' && sendMessage()} />
</div>
);
}
This approach requires ~60 lines of custom code but works with any backend and any AI provider.
Method 2: Vercel AI SDK useChat Hook
The Vercel AI SDK reduces the React integration to a single hook. It handles streaming, message state, input management, and error handling.
Installation:
npm install ai @ai-sdk/openai
Backend (Next.js API route or standalone):
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4.1-mini'),
messages,
});
return result.toDataStreamResponse();
}
React component -- the entire thing:
'use client';
import { useChat } from 'ai/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading, error } = useChat();
return (
<div>
{messages.map(m => (
<div key={m.id} className={m.role}>
{m.content}
</div>
))}
{error && <div className="error">{error.message}</div>}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} disabled={isLoading} />
<button type="submit" disabled={isLoading}>Send</button>
</form>
</div>
);
}
The useChat hook provides:
messages: Array of all messages with roles and contentinput/handleInputChange: Controlled input statehandleSubmit: Form submission handlerisLoading: Boolean for loading stateerror: Error object for error handlingstop: Function to abort streamingreload: Function to regenerate the last responseappend: Function to add messages programmatically
Switching providers takes one line on the backend:
import { anthropic } from '@ai-sdk/anthropic';
// model: anthropic('claude-haiku-3.5')
import { google } from '@ai-sdk/google';
// model: google('gemini-2.0-flash')
The React component stays identical. This is the fastest path from zero to a working AI chat in React.
Method 3: Direct Provider SDKs
Use provider SDKs when you need provider-specific features like function calling, structured outputs, or vision capabilities.
OpenAI SDK with React (function calling example):
// Backend
const response = await client.chat.completions.create({
model: 'gpt-4.1-mini',
messages,
tools: [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get current weather for a city',
parameters: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
},
required: ['city'],
},
},
},
],
stream: true,
});
Anthropic SDK with React (streaming):
// Backend
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const stream = client.messages.stream({
model: 'claude-haiku-3.5',
max_tokens: 1024,
messages,
});
for await (const event of stream) {
if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
res.write(`data: ${JSON.stringify({ content: event.delta.text })}\n\n`);
}
}
Both SDKs use Server-Sent Events (SSE) for streaming. The React client-side code is the same regardless of which provider SDK you use on the backend. Read our streaming tutorial for detailed SSE implementation.
AI Provider Comparison for React Apps
TokenMix.ai benchmarks all major providers monthly. Here is how they compare for React app integration.
| Dimension | OpenAI | Anthropic | DeepSeek | |
|---|---|---|---|---|
| Best Model for React | GPT-4.1 mini | Claude Haiku 3.5 | Gemini 2.0 Flash | DeepSeek V4 |
| Input Price | $0.40/M | $0.80/M | $0.10/M | $0.30/M |
| Output Price |