Build the interface in React, but send text to an AI provider through a server-side endpoint. That boundary keeps provider credentials out of browser code and gives you a place to validate input, define the analysis task, and return a predictable result. This tutorial uses a small text-summary workflow as an example; the same structure can support sentiment analysis, classification, or extraction.
Choose how to start the React app
For a new app, React recommends starting with a framework: “If you want to build a new app or website with React, we recommend starting with a framework.” The React guide to creating a React app also recognizes cases where starting from scratch makes sense, such as when frameworks do not fit your constraints or you want to learn the fundamentals.
| Approach | When it fits | What you need to decide |
|---|---|---|
| Framework | You want to build an application and a framework’s conventions and capabilities fit your deployment needs. | Which framework and deployment setup to use, and how to implement the server route that calls the AI provider. |
| From scratch | You have a constraint frameworks do not meet, are building a framework, or want to learn React fundamentals. | How to handle routing, data fetching, server endpoints, and other common application concerns. |
These are infrastructure choices, not a guarantee that one approach is faster, cheaper, or more secure. A from-scratch setup can still include a server endpoint; the important requirement is that secret-bearing provider requests run on the server.
Define the analysis before building the interface
“Analyze this text” is too vague for a useful product. Decide what the app should return, then design the provider instruction and response shape around that task. The example below asks for a concise summary and a short list of key points; replace those with task-specific instructions if you are building sentiment analysis, classification, or extraction.
#1 Best Overall
- Input: one text field and a clearly explained size limit appropriate to your application.
- Output: a summary string and an array of key-point strings.
- Failure behavior: show a useful error and let the user edit or retry.
- Text handling: tell users what happens to submitted text, and check the chosen provider’s current data-handling, retention, and safety terms before making privacy promises.
Do not present generated output as guaranteed to be correct. The prompt, response validation, and evaluation need to match the selected task and provider.
Plan the components and state
Use the interface to identify component boundaries and the minimum state needed to drive it. React’s Thinking in React describes breaking a UI into components, identifying minimal state, assigning ownership of state changes, and connecting components through data flow. For this workflow, a sensible division is:
- TextAnalysisForm: owns or receives the draft text and submits it.
- AnalysisResult: displays a completed summary and its key points.
- App: coordinates request status, errors, and the latest result.
Model the request lifecycle explicitly: ready, submitting, complete, and error. Keeping these states distinct makes it clear when to disable submission, when to show progress, and when to offer a retry.
Create a server endpoint for the provider call
Use a server route provided by your framework or backend. The route should accept a request, validate the submitted text, call the chosen AI provider using a server-side credential, and return a structured response your React UI can render. The endpoint shape and provider SDK vary; the following is framework-neutral pseudocode for the responsibilities, not drop-in code for a particular platform:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteRank #3
POST /api/analyze
Request: { "text": "..." }
Response: { "summary": "...", "keyPoints": ["...", "..."] }
- Reject malformed requests and empty or unsuitable input before sending it to the provider.
- Build a provider request with instructions for the selected task and the requested output structure.
- Call the provider from the server using a secret loaded from server-side configuration.
- Validate the returned content before responding; return a clear error if it cannot be used as the expected structure.
- Send the result to the client as JSON, or choose streaming deliberately if the interface needs partial output.
Never put a provider secret in React browser code or a value that is bundled for the client. TanStack AI’s Quick Start illustrates a React client connected to a server route and explicitly says not to send the API key to the browser. Its server-sent-event streaming example is one library’s approach, not a requirement: a simple request/response endpoint is sufficient for a result that arrives as one completed object.
Server rendering is a separate concern. React documents browser rendering APIs under react-dom/client and server rendering APIs under react-dom/server in its reference overview. Rendering a page on a server does not itself make an AI provider call safe; keep the credential-bearing call in server-side code.
Rank #4
Connect the React form to the endpoint
The client sends only the user’s text to your own endpoint. It does not need the provider key or provider-specific credentials. Here is a minimal React component for the stated response shape; it assumes the endpoint returns JSON with summary and keyPoints, and returns a non-success status for failures.
import { useState } from "react";
export function TextAnalysisForm() {
const [text, setText] = useState("");
const [status, setStatus] = useState("ready");
const [result, setResult] = useState(null);
const [error, setError] = useState("");
async function handleSubmit(event) {
event.preventDefault();
setStatus("submitting");
setError("");
setResult(null);
try {
const response = await fetch("/api/analyze", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text }),
});
if (!response.ok) {
throw new Error("The analysis could not be completed.");
}
const data = await response.json();
if (
typeof data.summary !== "string" ||
!Array.isArray(data.keyPoints) ||
!data.keyPoints.every((point) => typeof point === "string")
) {
throw new Error("The server returned an unexpected result.");
}
setResult(data);
setStatus("complete");
} catch (err) {
setError(err instanceof Error ? err.message : "An unexpected error occurred.");
setStatus("error");
}
}
return (
<section>
<form onSubmit={handleSubmit}>
<label htmlFor="analysis-text">Text to analyze</label>
<textarea
id="analysis-text"
value={text}
onChange={(event) => setText(event.target.value)}
required
/>
<button disabled={status === "submitting" || !text.trim()}>
{status === "submitting" ? "Analyzing…" : "Analyze text"}
</button>
</form>
{status === "submitting" && <p role="status">Analysis in progress…</p>}
{status === "error" && <p role="alert">{error}</p>}
{result && (
<div aria-live="polite">
<h2>Summary</h2>
<p>{result.summary}</p>
<h3>Key points</h3>
<ul>
{result.keyPoints.map((point, index) => (
<li key={`${index}-${point}`}>{point}</li>
))}
</ul>
</div>
)}
</section>
);
}
In JSX, the code uses standard React event handlers and state. The server remains responsible for provider-specific request construction and for validating its own output; checking the client response shape helps the UI avoid rendering unexpected data, but does not replace server validation.
Best Value
Handle errors and submitted text deliberately
A useful first version should distinguish an invalid input from a provider or network failure where possible, rather than treating every problem as a successful empty result. Keep the form available after an error so the user can correct the text or retry. If you impose a length limit, enforce it at the server boundary too, and explain the limit in the interface.
Quick Recap
- Do not log submitted text or expose it in error messages unless your product has a clear reason and appropriate safeguards.
- Use the provider’s current documentation to determine how it handles submitted data; do not claim that text is private, retained, or deleted without support for the exact provider and configuration you use.
- For task-specific quality, evaluate representative inputs and outputs for the task you actually intend to support; a valid JSON response alone does not establish that an analysis is accurate.
Test the complete flow
- Submit valid text and confirm that the server route receives it and returns the agreed result structure.
- Submit blank or malformed input and verify that the server rejects it without making an unnecessary provider call.
- Simulate a failed request and confirm the error state appears and the user can edit or retry.
- Return an unexpected result shape and verify it is rejected rather than rendered as if valid.
- Inspect the browser bundle and network requests to ensure no provider secret is exposed to the client.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

