Courses Curriculum Cities Blog Enroll Now
Build the React Frontend · Day 3 of 5 ~45 minutes

Day 3: Build the React Frontend

Build the interface users interact with. Fetch from your FastAPI backend, display results clearly, and handle loading states and errors gracefully.

1
Day 1
2
Day 2
3
Day 3
4
Day 4
5
Day 5
What You'll Build

A complete React frontend: text input, three analysis buttons, loading spinner, and a results panel that displays summary, key points, and generated questions in a clean layout.

1
Section 1 · 10 min

React + Axios Setup

javascriptsrc/App.js
import { useState } from 'react';
import axios from 'axios';

const API = 'http://localhost:8000';

function App() {
  const [text, setText] = useState('');
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const callAPI = async (endpoint) => {
    setLoading(true); setError(null);
    try {
      const res = await axios.post(`${API}/${endpoint}`, { text });
      setResult(res.data);
    } catch (e) {
      setError(e.response?.data?.detail || 'Something went wrong');
    } finally {
      setLoading(false);
    }
  };
2
Section 2 · 15 min

The JSX Template

javascriptsrc/App.js (continued)
  return (
    <div style={{maxWidth:'760px',margin:'0 auto',padding:'40px 20px'}}>
      <h1>AI Document Analyzer</h1>

      <textarea
        value={text}
        onChange={e => setText(e.target.value)}
        placeholder="Paste your text here..."
        rows={8}
        style={{width:'100%',padding:'12px',fontSize:'15px'}}
      />

      <div style={{display:'flex',gap:'10px',marginTop:'12px'}}>
        {['analyze', 'summarize', 'questions'].map(ep => (
          <button key={ep} onClick={() => callAPI(ep)}
            disabled={loading || !text}
            style={{padding:'10px 20px',textTransform:'capitalize'}}>
            {loading ? 'Loading...' : ep}
          </button>
        ))}
      </div>

      {error && <p style={{color:'red'}}>{error}</p>}
      {result && <pre>{JSON.stringify(result, null, 2)}</pre>}
    </div>
  );
}
export default App;
3
Section 3 · 20 min

Better Results Display

Replace the raw JSON display with a proper UI that renders each result type correctly:

javascriptsrc/ResultPanel.js
function ResultPanel({ result }) {
  if (!result) return null;
  return (
    <div style={{marginTop:'24px',padding:'20px',border:'1px solid #e0e0e0',borderRadius:'8px'}}>
      {result.summary &&
        <div><h3>Summary</h3><p>{result.summary}</p></div>}
      {result.key_points?.length > 0 &&
        <div><h3>Key Points</h3>
          <ul>{result.key_points.map((pt,i) =>
            <li key={i}>{pt}</li>
          )}</ul></div>}
      {result.sentiment &&
        <p>Sentiment: <strong>{result.sentiment}</strong></p>}
    </div>
  );
}
export default ResultPanel;

What You Learned Today

  • How React state management works: useState for text, result, loading, and error
  • The callAPI pattern: setLoading → try/catch axios → setResult/setError → finally setLoading(false)
  • How to render different result shapes conditionally using optional chaining (?.)
  • Why disabling buttons during loading prevents double-submission bugs
Your Challenge

Go Further on Your Own

  • Add a character counter below the textarea that shows current length and max allowed
  • Add a 'Clear' button that resets text and result to empty
  • Build a tabbed results view: when the user runs multiple analyses on the same text, show each result in a separate tab
Day 3 Complete

Nice work. Keep going.

Day 4 is ready when you are.

Continue to Day 4
Course Progress
60%

Want live instruction and hands-on projects? Join the AI bootcamp — 3 days, 5 cities.

Finished this lesson?