React Frontend Development
Building Interactive UIs with Modern React
Course lectures and practices for JavaScript full‑stack web development with AI‑assisted workflows.
React Frontend Development 🚀
- Explain React’s component-based architecture and its advantages over vanilla JavaScript DOM manipulation
- Build and compose functional React components using JSX and props
- Manage state and handle user events in React applications
- Integrate external API data using React hooks (
useState,useEffect) - Structure a real-world React project for maintainability and scalability
✅ Solid understanding of JavaScript ES6+ (functions, objects, arrays, arrow functions, destructuring)
✅ Familiarity with HTML/CSS and basic DOM concepts
✅ Basic command-line and npm usage
✅ Completion of Session 2: JavaScript for React
💡 If you need a refresher: Review Session 2 materials on JavaScript fundamentals before continuing.
🎯 Today’s Mission
- Part 1: React Fundamentals (components, JSX, props, basic state)
- Part 2: Interactive Features (events, forms, data fetching, real app structure)
Using: fullstack-minimal-app as our foundation
Goal: Build a complete React frontend ready for backend integration! 🎉
Philosophy: Learn by building, AI-assisted development, practical focus
💡 Why React? (The JavaScript Pain)
Remember vanilla JavaScript from Session 2?
// Manual DOM manipulation (tedious!)
const button = document.querySelector('#loadBtn');
const output = document.querySelector('#output');
button.addEventListener('click', async () => {
output.innerHTML = 'Loading...';
const response = await fetch('/api/data');
const data = await response.json();
// Manual HTML creation (error-prone!)
output.innerHTML = '';
data.forEach(item => {
const div = document.createElement('div');
div.textContent = item.name;
output.appendChild(div);
});
});React Makes It Elegant:
function DataDisplay() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const loadData = async () => {
setLoading(true);
const response = await fetch('/api/data');
const result = await response.json();
setData(result);
setLoading(false);
};
return (
<div>
<button onClick={loadData}>Load Data</button>
{loading ? <p>Loading...</p> : null}
{data.map(item => <div key={item.id}>{item.name}</div>)}
</div>
);
}React = Declarative: “Here’s what the UI should look like” not “Here’s how to build it”
🎯 Real-World Software Engineering Challenge
Scenario: You’re building a dashboard for a fast-growing startup. The product team adds 5 new features every sprint. How do you keep your UI code maintainable as complexity grows?
Answer: Component-based architecture! Each feature becomes a reusable, testable component that can evolve independently. This is why companies like Facebook created React—to manage massive, evolving UIs.
Key Principles:
- Maintainability: Components isolate complexity
- Scalability: Add features without rewriting existing code
- Testability: Test components in isolation
- Collaboration: Teams can work on different components simultaneously
🚀 React in the Real World
What React Solves
- Component Reusability: Write once, use everywhere
- State Management: UI updates automatically
- Virtual DOM: Efficient updates
- Developer Experience: Great tools and ecosystem
- Community: Huge library ecosystem
Industry Usage
- Netflix: Entire streaming interface
- Instagram: Web platform
- Airbnb: Booking and host platforms
- Uber: Driver and rider apps
- Discord: Chat interface
💼 Industry Context
React’s component model has become the industry standard for building modern web applications. Understanding React prepares you for:
- Job Market: React is the #1 frontend framework (used by 40%+ of web developers)
- Next.js (React with server-side rendering)
- React Native (Mobile app development)
- Remix, Gatsby, and other React-based frameworks
Learning React is not just about one library—it’s about understanding the component-based architecture pattern that dominates modern web development.
🛠️ Setup and Development Tools
What You Need to Run React Locally
Essential Tools:
- Node.js (v18+ recommended)
- JavaScript runtime for running development tools
- Includes npm (Node Package Manager)
- Download: nodejs.org
- npm (comes with Node.js)
- Package manager for installing React and dependencies
- Used to run development scripts
- Vite (build tool)
- Fast development server with Hot Module Replacement (HMR)
- Modern alternative to Create React App
- Build tool optimized for React development
Quick Start (if starting from scratch):
# Install Node.js from nodejs.org if not already installed
# Create new React project with Vite (Run this command in terminal)
npm create vite@latest my-react-app -- --template react
# Navigate and install
cd my-react-app # Navigate into the project directory
npm install
# Start development server
npm run devFor this course: We provide a ready-made fullstack app, so you can focus on learning React rather than configuration! ⚡
Pedagogical Approach: Rather than spending time on tooling configuration, we provide fullstack-minimal-app that includes:
- ✅ React + Vite pre-configured
- ✅ Tailwind CSS for styling
- ✅ Node.js/Express backend (ready for next session)
- ✅ Database integration setup
- ✅ Project structure following industry best practices
Learning Focus: You concentrate on React concepts, not build configuration. Once you understand React, you’ll easily set up projects from scratch.
🔧 Setup: fullstack-minimal-app
We’ll use the provided minimal app as our foundation
See GitHub repo for Quickstart instructions. With Docker and devcontainer support all set up for you including Frontend and Backend and Database.
# Start development (opens both frontend and backend)
npm run dev
# Frontend: http://localhost:5173
# Backend: http://localhost:4000 (we'll use next session)What you get:
fullstack-minimal-app/
├── frontend/ ← React app (Vite + React)
│ ├── src/
│ │ ├── App.jsx ← Main component
│ │ ├── main.jsx ← Entry point
│ │ └── components/ ← Our components go here
│ └── package.json
├── backend/ ← Node.js API (next session)
└── package.json ← Root scripts and dependencies
🤖 AI Development Setup
VS Code Extensions:
- GitHub Copilot and Copilot Chat
- ES7+ React snippets
- Tailwind CSS IntelliSense
When You’ll have understood the basics, you can use AI to help generate components and boilerplate code.
AI Prompting Pattern
Context: React functional component for [purpose]
Task: Create component that [specific functionality]
Constraints: Modern React hooks, Tailwind CSS
Output: Complete JSX componentfor exemple :
Context: React component for displaying product reviews
Task: Create a ReviewCard component with these props:
- review: { id, user, comment, rating }
Constraints: Modern React hooks, Tailwind CSS
Output: Complete JSX componentThe 3 main concepts of React
Only three core concepts to master:
- Components: Reusable building blocks of UI
- Props: Data passed into components
- State: Data that changes over time and triggers UI updates
🧩 Components: The Building Blocks
A React component is a function that returns JSX
- JSX = JavaScript + XML (HTML-like syntax)
- Components are reusable, composable pieces of UI
- The following examples define a simple component that displays a welcome message.
function WelcomeMessage() {
return (
<div className="p-4 bg-blue-50 rounded">
<h1 className="text-2xl font-bold text-blue-800">
Welcome to React! 👋
</h1>
<p className="text-blue-600">
You're building with components now!
</p>
</div>
);
}Using Components
- Use JSX components like HTML tags
- In the main App component, you can include
WelcomeMessagemultiple times - You can also nest components inside each other
function App() {
return (
<div className="container mx-auto p-4">
<WelcomeMessage />
<WelcomeMessage />
<WelcomeMessage />
</div>
);
}Component Key Concepts
- Components are reusable (use multiple times)
- Components are composable (nest inside each other)
- Components use JSX (looks like HTML, but it’s JavaScript) : easy to read and write
Expression Examples
In JSX, you can embed any JavaScript expression inside {}:
- The code will be evaluated and the result inserted into the HTML
- On the client side, this allows dynamic rendering based on variables, function calls, …
// Variables
// {title} is a JavaScript variable
// If title = "Welcome to React!"
// Returns <h1>Welcome to React!</h1>
<h1>{title}</h1>
// Function calls
// {formatDate} is a JavaScript function
// if date is a Date object
// Returns formatted date string
<p>{formatDate(date)}</p>
// Array methods
// if products = [{id: 1, name: 'Item 1'}, {id: 2, name: 'Item 2'}]
// Returns list of product names
{products.map(p => <div key={p.id}>{p.name}</div>)}⚠️ In JSX, Always Return a Single Root Element
- A component must return a single root element.
- Wrap multiple elements in a
<div>or React Fragment<>...</>.
// ❌ Wrong
return (
<h1>Title</h1>
<p>Content</p>
)// ✅ Correct
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
)📝 JSX: JavaScript + HTML
JSX lets you write HTML-like syntax in JavaScript
function UserProfile() {
const name = "Alice Johnson";
const age = 25;
const isOnline = true;
return (
<div className="user-card">
{/* JavaScript expressions in {} */}
<h2>Welcome, {name}!</h2>
<p>Age: {age}</p>
{/* Conditional rendering */}
{isOnline && (
<span className="status online">🟢 Online</span>
)}
{/* Self-closing tags need / */}
<img src={`/avatar/${name}.jpg`} alt="Profile" />
<br />
{/* className not class */}
<button className="btn-primary">
Follow
</button>
</div>
);
}HTML vs JSX Differences
| HTML | JSX | Why? | Explanation |
|---|---|---|---|
class |
className |
class is reserved in JS |
Applies CSS classes to an element (maps to element.className). |
for |
htmlFor |
for is reserved in JS |
Associates a label with an input element (sets htmlFor attribute). |
onclick |
onClick |
camelCase convention | Attaches a click event handler function to the element. |
style="color: red" |
style={{color: 'red'}} |
JS object syntax | Sets inline styles using a JavaScript object (applies CSS properties). |
📦 Props: Passing Data
Props make components reusable by passing data into them
- A JSX attribute is like a function argument
- Props are passed to components in a similar way to how arguments are passed to functions
- In the example below, we create a
ProductCardcomponent that accepts props forname,price,image, andinStockstatus.
function ProductCard({ name, price, image, inStock }) {
return (
<div className="border rounded-lg p-4 shadow-md">
<img src={image} alt={name} className="w-full h-48 object-cover rounded" />
<h3 className="text-lg font-semibold mt-2">{name}</h3>
<p className="text-xl font-bold text-green-600">${price}</p>
{inStock ? (
<button className="w-full bg-blue-600 text-white py-2 rounded mt-2">
Add to Cart
</button>
) : (
<button className="w-full bg-gray-400 text-white py-2 rounded mt-2" disabled>
Out of Stock
</button>
)}
</div>
);
}Using the Component with Different Data
function ProductGrid() {
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<ProductCard
name="Wireless Headphones"
price={99.99}
image="/images/headphones.jpg"
inStock={true}
/>
<ProductCard
name="Bluetooth Speaker"
price={79.99}
image="/images/speaker.jpg"
inStock={false}
/>
<ProductCard
name="Smart Watch"
price={299.99}
image="/images/watch.jpg"
inStock={true}
/>
</div>
);
}Props Pattern: Define once, use with different data!
🤖 AI Practice: Product Card Component
Prompt for AI:
Context: React component for displaying product reviews
Task: Create a ReviewCard component with these props:
- author (string): reviewer name
- rating (number): 1-5 stars
- title (string): review title
- content (string): review text
- date (string): review date
- source (string): "Amazon" | "BestBuy" | "Walmart"
Requirements:
- Display star rating as ★ symbols
- Show source with colored badge (Amazon=orange, BestBuy=blue, Walmart=green)
- Responsive design with Tailwind CSS
- Modern functional component syntax
Output: Complete ReviewCard.jsx component
After AI generates: 1. Create the component in frontend/src/components/ReviewCard.jsx 2. Test it in your App component 3. Try it with different prop values
🔄 State: Making Components Interactive
State = data that can change and triggers UI updates
- State is managed with the
useStatehook - Each piece of state is independent
- State updates cause the component to re-render with new values
- State is local to the component (not shared unless passed via props)
- the following example shows a simple counter component using state.
import { useState } from 'react';
function Counter() {
// [value, setter] = useState(initialValue)
// value = current state
// setCount = function to update state
const [count, setCount] = useState(0);
return (
<div className="text-center p-4">
<h2 className="text-2xl mb-4">Count: {count}</h2>
<div className="space-x-2">
<button
onClick={() => setCount(count - 1)}
className="px-4 py-2 bg-red-500 text-white rounded"
>
-1
</button>
<button
onClick={() => setCount(count + 1)}
className="px-4 py-2 bg-green-500 text-white rounded"
>
+1
</button>
<button
onClick={() => setCount(0)}
className="px-4 py-2 bg-gray-500 text-white rounded"
>
Reset
</button>
</div>
</div>
);
}Key Points in State Management
- Always use the setter function (
setCount, notcount = 5) - State updates trigger re-render
- Each component has its own state
🧠 Why not use regular variables?
// ❌ This won't work!
function BrokenCounter() {
let count = 0;
const increment = () => {
count = count + 1; // Updates variable...
console.log(count); // Logs correctly...
// But UI doesn't update! 😢
};
return <button onClick={increment}>Count: {count}</button>;
}// ✅ This works!
function WorkingCounter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1); // React knows to re-render!
};
return <button onClick={increment}>Count: {count}</button>;
}The problem: React doesn’t know when regular variables change, so it can’t re-render the UI.
The solution: useState tells React “this value matters, re-render when it changes!”
🎮 Interactive Features : Event Handling
React handles events with camelCase: onClick, onChange, onSubmit
- A component can respond to user actions via event handlers
- Event handlers are functions passed to components as props
- When the event occurs, the handler function is called
- Event handlers receive an event object as an argument
- Common events: click, change, submit, mouse enter/leave, key press
- Exemple: when a button is clicked, update state
Minimal Event Example
function InteractiveDemo() {
const [text, setText] = useState('');
return (
<div>
<button onClick={() => alert('Clicked!')}>Click</button>
<input value={text} onChange={e => setText(e.target.value)} placeholder="Type..." />
<p>Current: {text}</p>
</div>
);
}📝 Forms & Controlled Inputs
React controls form inputs = “Controlled Components”
- Form inputs (text, select, checkbox) maintain their own state
- In React, we control the input state via
useState - The input’s
valueis tied to state, andonChangeupdates the state - This way, React is the “single source of truth” for form data
Product Search Form — Minimal
- The following is a minimal product search form component with a controlled text input and a submit handler that logs the search term.
function ProductSearch() {
const [term, setTerm] = useState('');
const handleSubmit = (e) => {
e.preventDefault(); // Prevent page reload
console.log('Search:', term);
// here add code to do something with the search term
// e.g. call an API to fetch search results
// and then update state with results, so the UI updates
};
return (
<form onSubmit={handleSubmit} className="max-w-md mx-auto p-4">
<label className="block text-sm font-medium mb-1">Search</label>
<div className="flex gap-2">
<input
value={term}
onChange={e => setTerm(e.target.value)}
className="flex-1 border rounded px-3 py-2"
placeholder="Type product name..."
aria-label="Search products"
/>
<button className="bg-blue-600 text-white px-4 py-2 rounded" type="submit">Go</button>
</div>
</form>
);
}Pattern: value={state} + onChange={setState} = Controlled Input
Exercise: Build a “Product Filter” form component with: - Text input for search term - Checkbox for “In stock only” - Range slider for price (0-1000) - Display all current filter values below the form
Why this pattern?: React is the “single source of truth” for form data. This makes it easy to validate, submit, or reset forms programmatically.
🌐 API Integration with useEffect
useEffectis a React hook for managing side effects (e.g. data fetching, subscriptions)- useffect takes two arguments:
- A function to run (the effect)
- An array of dependencies (when to re-run the effect)
- It runs after the component renders, making it ideal for API calls.
- You can think of it as a way to perform actions “after” the component has rendered.
Fetching Data on Component Mount
- The following example fetches a list of products from an API when the component mounts.
- Fetch will call the API and store the results in state
- The component re-renders with the fetched data
- Note
awaitandasyncare used for asynchronous call
- The following is a minimal example of fetching product names from an API and displaying them in a list.
import { useState, useEffect } from 'react';
function ProductList() {
const [names, setNames] = useState([]);
useEffect(() => {
// To avoid setting state on unmounted component
let mounted = true;
(async () => {
try {
const res = await fetch('http://localhost:4000/api/products');
if (!res.ok) throw new Error('fetch failed');
const data = await res.json();
if (mounted) setNames(data.map(p => p.name));
} catch (err) {
if (mounted) setNames([]);
}
})();
return () => { mounted = false; };
}, []);
return (
<ul className="list-disc pl-5">
{names.length === 0 ? (
<li className="text-sm text-gray-500">No products (or server not running)</li>
) : (
names.map((n, i) => <li key={i}>{n}</li>)
)}
</ul>
);
}A Minimal Example : Fullstack mini app
- Browse the frontend components: see
frontend/src/components/in the repository to inspect sample components we use in class. - Read the project docs:
- fullstack-minimal-app README — project quickstart and architecture overview.
- LEARNING_NOTES.md — students notes.
🏁 Session Wrap-up
What You’ve Learned Today:
React Fundamentals ✅
- Components and JSX syntax
- Props for data passing
- State with useState hook
- Event handling patterns
- Controlled form inputs
- useEffect for side effects
Practical Skills ✅
- Building reusable components
- Managing application state
- Handling user interactions
- API integration patterns
- Error handling and loading states
Application Structure ✅
- Component organization
- Data flow patterns
- State management strategies
- Real-world app architecture
AI-Assisted Development ✅
- Effective prompting techniques
- Code verification skills
- Iterative development process
- Debugging generated code