AI-чат на React через AI Gateway: запросы к своему бэкенду
Как сделать чат-компонент на React с AI Gateway правильно: React ходит в ваш backend-прокси, а ключ живёт только на сервере. Пример компонента и потокового вывода ответа.
Чат-компонент на React не должен обращаться к API модели напрямую: код фронтенда виден пользователю, и ключ утечёт. Правильная схема — React шлёт сообщение в ваш собственный backend-прокси, а тот уже ходит в AI Gateway с ключом. Ниже — компонент и вариант с потоковым выводом ответа.
sk-aigate-… в код React или в переменные с префиксом VITE_/NEXT_PUBLIC_ — всё это попадает в бандл браузера и легко читается. Ключ хранится только на сервере, а React обращается к вашему эндпоинту-прокси (например, Next.js route handler или FastAPI).Подготовка
На стороне сервера настройте эндпоинт (/api/chat), который принимает текст, обращается к https://ai-gatewey.ru/v1 с ключом из окружения и возвращает ответ. Готовые примеры прокси: Next.js и FastAPI. Компонент ниже работает с любым таким эндпоинтом.
Реализация
- Простой чат-компонент
Отправляем сообщение на свой прокси
/api/chatи показываем ответ. Ключа здесь нет — только вызов собственного бэкенда:import { useState } from "react"; export function Chat() { const [input, setInput] = useState(""); const [reply, setReply] = useState(""); const [loading, setLoading] = useState(false); async function send() { setLoading(true); const res = await fetch("/api/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: input }), }); const data = await res.json(); setReply(data.reply); setLoading(false); } return ( <div> <textarea value={input} onChange={(e) => setInput(e.target.value)} /> <button onClick={send} disabled={loading}> Отправить </button> <p>{reply}</p> </div> ); } - Потоковый вывод ответа
Если прокси стримит ответ (
text/plainили SSE), читаем тело как поток и дописываем текст по мере поступления — так ответ «печатается»:async function sendStream() { const res = await fetch("/api/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: input }), }); const reader = res.body!.getReader(); const decoder = new TextDecoder(); setReply(""); for (;;) { const { value, done } = await reader.read(); if (done) break; setReply((prev) => prev + decoder.decode(value)); } }
Какие модели подойдут
Модель выбирается на сервере, а не в компоненте. Для интерактивного чата важна скорость первого токена — обычно берут быструю модель, оставляя флагман для сложных запросов:
| Модель | Ввод, ₽/1М | Вывод, ₽/1М | Контекст |
|---|---|---|---|
| DeepSeek: DeepSeek V3 | 31 | 125 | 128K |
| OpenAI: GPT-5.4 Mini | 118 | 705 | 400K |
| Anthropic Claude Haiku Latest | 157 | 784 | 200K |
Частые вопросы
Почему нельзя обращаться к AI Gateway прямо из React?
Код фронтенда доступен любому пользователю, а значит и ключ, вшитый в бандл. Его тут же используют посторонние, и весь расход ляжет на вас. Ключ должен оставаться на сервере, а браузер обращается к вашему прокси.
А если у меня чисто фронтенд без бэкенда?
Тогда прокси-эндпоинт можно поднять как serverless-функцию (Vercel, Cloudflare Workers, Netlify Functions) — это несколько строк кода, а ключ остаётся в переменных окружения платформы.
Как хранить историю диалога?
Держите массив сообщений в состоянии компонента и передавайте его в теле запроса на прокси; собирать финальный messages для модели должен сервер. Старые сообщения обрезайте, чтобы экономить токены.
Чат на React с AI — начните с ключа на сервере
Получить ключ