Practice 3 — React Review Aggregator Frontend
Build Interactive Product Review Interface with React
Course lectures and practices for JavaScript full‑stack web development with AI‑assisted workflows.
All AI prompts in this practice are examples. Feel free to modify them to suit your style or needs. This will improve your prompt engineering skills and help you get better results from the AI and to have a better final project.
Getting started — Small hands-on exercises (use AI)
Start with three tiny exercises that use the AI to scaffold minimal React components. They are intentionally simple and build up from static to interactive.
Before working on the final project, the easiest way to get started is to create a minimal Vite React app and paste the exercise components into it. Below are copy-paste commands you can run in a terminal (requires Node.js 18+ and npm).
- Create the React app with Vite :
# This create the react app in the frontend directory
npm create vite@latest frontend -- --template reactyou can start and open in your browser.
- Install dependencies and common helper libs:
# Install dependencies
# IN ANOTHER TERMINAL otherwise the app will stop
# PropTypes (used in exercises)
npm install prop-types- If you stopped the server run it :
npm run dev
# Opens http://localhost:5173 by defaultWhere to paste the exercises
- Create
src/components/and paste components there. - Use
src/App.jsxto import and test the components as shown in the exercises.
Update src/App.jsx
After creating the Vite app, replace the generated src/App.jsx with a small harness that imports and renders your exercise components. Paste the example below into src/App.jsx (adjust imports to match files you created):
import React from 'react';
// NOTE: The components below are created by the quickstart exercises in this document.
// To avoid import errors when you paste this file before doing the exercises,
// the imports and component usages are commented out. After you create the files
// under `src/components/`, uncomment the corresponding import and JSX.
// import CustomerStatic from './components/CustomerStatic'; // exercise 1
// import CustomerWithProps from './components/CustomerWithProps'; // exercise 2
// import CustomerWithState from './components/CustomerWithState'; // exercise 3
function App() {
return (
<div className="min-h-screen bg-gray-50 p-6">
<div className="max-w-3xl mx-auto space-y-6">
<h1 className="text-2xl font-bold">Component Quickstart</h1>
<section>
<h2 className="text-lg font-semibold">Static</h2>
{/* CustomerStatic (exercise 1) - uncomment after creating `src/components/CustomerStatic.jsx` */}
{/* <CustomerStatic /> */}
<div className="text-sm text-gray-500">CustomerStatic will be created by exercise 1 — uncomment when ready.</div>
</section>
<section>
<h2 className="text-lg font-semibold">With props</h2>
{/* CustomerWithProps (exercise 2) - uncomment after creating `src/components/CustomerWithProps.jsx` */}
{/* <CustomerWithProps name="Alice" email="alice@example.com" /> */}
<div className="text-sm text-gray-500">CustomerWithProps will be created by exercise 2 — uncomment when ready.</div>
</section>
<section>
<h2 className="text-lg font-semibold">With state</h2>
{/* CustomerWithState (exercise 3) - uncomment after creating `src/components/CustomerWithState.jsx` */}
{/* <CustomerWithState name="Bob" email="bob@example.com" /> */}
<div className="text-sm text-gray-500">CustomerWithState will be created by exercise 3 — uncomment when ready.</div>
</section>
</div>
</div>
);
}
export default App;Then run the dev server (npm run dev) and open the app to verify the components render.
- Static Customer component
- Goal: Create a presentational component that renders static customer information.
- File:
src/components/CustomerStatic.jsx - Instructions: Ask the AI to generate a small functional React component that returns a card with name, email, and an avatar placeholder. No props or state.
AI prompt example:
Create a React functional component `CustomerStatic.jsx` that renders a card with a customer name, email, and a round avatar placeholder. Use Tailwind CSS classes for simple styling and export the component as default.- Customer with props
- Goal: Convert the static component to accept props for
name,email, andavatarUrl. - File:
src/components/CustomerWithProps.jsx - Instructions: Use the AI to add PropTypes validation and make the component reusable.
AI prompt example:
Create a React component `CustomerWithProps.jsx` that accepts `name`, `email`, and `avatarUrl` props, displays them in the same card layout, and includes PropTypes. Add a short example of how to import and use the component in `App.jsx`.- Customer with local state
- Goal: Add a follow/unfollow button using
useStateso the component becomes interactive. - File:
src/components/CustomerWithState.jsx - Instructions: Ask the AI to create the component with a
followingboolean state, a button toggling it, accessible labels, and simple Tailwind styles. Show how a parentApp.jsxcan render the component and respond to a callback (e.g.,onFollowChange).
AI prompt example:
Create `CustomerWithState.jsx` that renders name/email/avatar and a 'Follow' button. Use `useState` to toggle following status and call an optional `onFollowChange(isFollowing)` prop when the state changes. Add PropTypes and Tailwind classes.Notes: - After generating each component with the AI, paste the code into the corresponding file under your frontend project and run the dev server to verify. - If you get browser errors, copy/paste them into the course chatbot (see Troubleshooting callout) for suggested fixes.
- Customer controlled form
- Goal: Create a controlled
CustomerFormcomponent that accepts name and email, validates them, and callsonSubmitwith the values. - File:
src/components/CustomerForm.jsx - Instructions: Use
useStateto manage inputs, show simple validation (required, email format), disable submit until valid, and callonSubmit({ name, email })on submit.
AI prompt example:
Create `CustomerForm.jsx` — a controlled React component with `name` and `email` inputs, local `useState` for each, simple validation (required, email regex), a disabled submit button until valid, and an `onSubmit` prop that receives the form values. Use Tailwind CSS and PropTypes.Use AI to add button to a CustomerForm in App
- Customer list & lifted state
- Goal: Build
CustomerList.jsxthat receives an array of customers and rendersCustomerWithStatefor each. Add UI to add new customers with theCustomerFormand keep the list in the parent usinguseState. - File:
src/components/CustomerList.jsx - Instructions: The parent should contain the array state, pass
onFollowChangedown to children, and show totals (total customers, followed count).
AI prompt example:
Create `CustomerList.jsx` that holds an array of customer objects in state, renders a `CustomerWithState` for each, and includes a `CustomerForm` to add new customers. Update counts (total, following) in the parent. Use Tailwind CSS and PropTypes; show a small empty-state message when no customers exist.Practice — React Review Aggregator Frontend
Prerequisites: React lecture completed, fullstack-minimal-app setup
Project: Multi-Source Product Review Aggregator frontend
Objective: Build React components for displaying and fetching product reviews
Here is a step -by-step guide to build the React frontend for the review aggregator project. You will create several components, integrate them, and connect to a mock API service. You have to adapt the AI prompts as needed to get the best results for what YOU want to achieve.
Complete React frontend for the review aggregator project:
- ✅ ProductHeader — Display product information
- ✅ ReviewFetcher — Button to fetch reviews from “external sources”
- ✅ ReviewStats — Statistics visualization (average rating, source breakdown)
- ✅ ReviewList — Display list of reviews with filtering
- ✅ ReviewCard — Individual review display component
Technologies: React hooks, Tailwind CSS, mock API integration
Foundation: Using fullstack-minimal-app/frontend as starting point
If the sample project repo isn’t set up yet, follow the instructions in the lecture notes to setup a react project with Vite and Tailwind CSS. It will be sufficient for this practice.
Part 1: Project Setup
Step 1.2: Create Component Structure
# Create components for reviews
mkdir -p src/components/reviews
mkdir -p src/services
# Create component files
touch src/components/reviews/ProductHeader.jsx
touch src/components/reviews/ReviewFetcher.jsx
touch src/components/reviews/ReviewStats.jsx
touch src/components/reviews/ReviewList.jsx
touch src/components/reviews/ReviewCard.jsx
# Create mock API service
touch src/services/mockReviewAPI.jsYour structure should be:
frontend/src/
├── components/
│ ├── reviews/
│ │ ├── ProductHeader.jsx
│ │ ├── ReviewFetcher.jsx
│ │ ├── ReviewStats.jsx
│ │ ├── ReviewList.jsx
│ │ └── ReviewCard.jsx
│ ├── ProductList.jsx # Already exists
│ └── ProductForm.jsx # Already exists
├── services/
│ └── mockReviewAPI.js
├── App.jsx
└── main.jsx
Part 2: Mock API Service
Exercise 2.1: Create Mock Review API
Use AI to generate the mock API service:
Prompt for AI:
Context: React frontend for Multi-Source Product Review Aggregator
Task: Create mockReviewAPI.js service that simulates backend API calls
Functions needed:
1. fetchProductReviews(productId) - Returns existing reviews for a product
2. triggerReviewFetch(productId) - Simulates fetching new reviews from external sources
3. getReviewStats(productId) - Returns aggregate statistics
Mock data:
- 15+ diverse reviews with fields: id, productId, source, author, rating, title, content, date
- Sources: "Amazon", "BestBuy", "Walmart"
- Ratings: 1-5 stars
- Realistic review content for a wireless headphones product
API simulation:
- Add delays (500ms-2s) to simulate network calls
- Return promises for async handling
- Include error simulation (10% chance)
Requirements:
- ES6 modules (export/import)
- JSDoc comments
- Realistic mock data
- Error handling simulation
Output: Complete mockReviewAPI.js fileSave the generated code to src/services/mockReviewAPI.js
Verify it works:
// Test in browser console
await import('/src/services/mockReviewAPI.js')
.then(m => m.fetchProductReviews('1'))
.then(console.log)
.catch(console.error);Part 3: React Components
Exercise 3.1: Create ReviewCard Component
Prompt for AI:
Context: React component for displaying individual product review
Task: Create ReviewCard.jsx component
Props:
- review: {
id: number,
source: string ("Amazon" | "BestBuy" | "Walmart"),
author: string,
rating: number (1-5),
title: string,
content: string,
date: string (ISO format)
}
Features:
- Star rating display (★★★★☆ format)
- Source badge with colors (Amazon=orange, BestBuy=blue, Walmart=green)
- Author name and relative date ("3 days ago")
- Review title (bold)
- Review content (with read more/less for long text)
- Responsive card layout
Requirements:
- React functional component with hooks
- Tailwind CSS styling
- PropTypes validation
- Accessible (ARIA labels)
- Mobile-responsive
Output: Complete ReviewCard.jsx componentTest the component:
// Example App.jsx that mounts the Review Aggregator page for local testing
import React from 'react';
import ReviewAggregatorPage from './components/reviews/ReviewAggregatorPage';
function App() {
return (
<div className="min-h-screen bg-gray-50 p-4">
{/* Pass a demo productId; component reads mock API */}
<ReviewAggregatorPage productId="1" />
</div>
);
}
export default App;Exercise 3.2: Create ReviewStats Component
Prompt for AI:
Context: React component displaying aggregate review statistics
Task: Create ReviewStats.jsx component
Props:
- stats: {
overallAverage: number (e.g., 4.2),
totalReviews: number,
sourceBreakdown: [
{ source: string, average: number, count: number }
],
ratingHistogram: { 1: number, 2: number, 3: number, 4: number, 5: number }
}
- loading: boolean (optional)
Features:
- Large overall average display (4.2★)
- Total review count
- Per-source breakdown (table or list)
- Rating histogram (horizontal bars)
- Loading skeleton when loading=true
Requirements:
- Tailwind CSS for styling
- No external chart libraries (use CSS for bars)
- PropTypes validation
- Loading state animation
Output: Complete ReviewStats.jsx componentExercise 3.3: Create ReviewList Component
Prompt for AI:
Context: React component for listing product reviews with filtering
Task: Create ReviewList.jsx component
Props:
- reviews: array of review objects
- loading: boolean
- onFilterChange: function
Features:
- Filter dropdown by source (All, Amazon, BestBuy, Walmart)
- Filter by rating (All, 5★, 4★+, 3★+, 2★+, 1★)
- Display filtered review count
- Map over reviews using ReviewCard component
- Empty state when no reviews
- Loading state with skeleton cards
State management:
- useState for sourceFilter and ratingFilter
- Filter reviews locally based on selected filters
- Call onFilterChange when filters change
Requirements:
- Import and use ReviewCard
- Tailwind CSS styling
- PropTypes validation
Output: Complete ReviewList.jsx componentExercise 3.4: Create ReviewFetcher Component
Prompt for AI:
Context: React component with button to fetch new reviews
Task: Create ReviewFetcher.jsx component
Props:
- productId: string
- onReviewsFetched: function (callback when new reviews are fetched)
Features:
- "Fetch Reviews" button (prominent styling)
- Loading state (button disabled, shows spinner)
- Success message after fetch ("Fetched X new reviews!")
- Error handling with retry button
- Progress indicator during fetch
Functionality:
- onClick calls triggerReviewFetch(productId) from mock API
- Handle loading, success, and error states
- Call onReviewsFetched with new reviews data
- Auto-clear messages after 3 seconds
Requirements:
- useState for loading, message, error states
- Import triggerReviewFetch from mock API
- Tailwind CSS styling
- PropTypes validation
Output: Complete ReviewFetcher.jsx componentExercise 3.5: Create ProductHeader Component
Simple component - can code manually or use AI:
// src/components/reviews/ProductHeader.jsx
import PropTypes from 'prop-types';
function ProductHeader({ productName, productImage, productPrice }) {
return (
<div className="bg-white rounded-lg shadow p-6 mb-6">
<div className="flex items-center space-x-4">
{productImage && (
<img
src={productImage}
alt={productName}
className="w-20 h-20 object-cover rounded"
/>
)}
<div>
<h1 className="text-2xl font-bold text-gray-900">{productName}</h1>
{productPrice && (
<p className="text-xl text-green-600 font-semibold">${productPrice}</p>
)}
</div>
</div>
</div>
);
}
ProductHeader.propTypes = {
productName: PropTypes.string.isRequired,
productImage: PropTypes.string,
productPrice: PropTypes.number,
};
export default ProductHeader;Part 4: Main Page Integration
Exercise 4.1: Create Main ReviewAggregatorPage
Prompt for AI:
Context: Main React page component integrating all review components
Task: Create ReviewAggregatorPage.jsx component
Features:
- Main page layout with ProductHeader at top
- ReviewFetcher component with callback handling
- ReviewStats component showing aggregate statistics
- ReviewList component showing individual reviews
- State management for reviews, stats, loading states
State management:
- reviews: array (starts empty)
- stats: object (starts null)
- loading: boolean for initial load
- fetchingNew: boolean for fetch button
Lifecycle:
- useEffect on mount: load existing reviews and calculate stats
- onReviewsFetched callback: add new reviews, recalculate stats
Layout:
- Mobile: Stack all components vertically
- Desktop: Stats sidebar, reviews main content area
Props:
- productId: string (default "1" for demo)
Requirements:
- Import all review components
- Import mock API functions
- useState and useEffect hooks
- Tailwind CSS responsive layout
- PropTypes validation
- Error handling for API calls
Output: Complete ReviewAggregatorPage.jsx componentExercise 4.2: Update App.jsx
Replace the content of App.jsx:
// src/App.jsx
import ReviewAggregatorPage from './components/reviews/ReviewAggregatorPage';
function App() {
return (
<div className="min-h-screen bg-gray-50">
<ReviewAggregatorPage productId="1" />
</div>
);
}
export default App;Part 5: Testing & Polish
Test Complete Flow
- Initial Load:
- Page loads with empty state
- “Fetch Reviews” button is prominent
- Fetch Reviews:
- Click fetch button
- Loading state shows
- After delay, reviews appear
- Stats update with aggregated data
- Filtering:
- Test source filter (All, Amazon, BestBuy, Walmart)
- Test rating filter (All, 5★, 4★+, etc.)
- Verify review count updates
- Responsive Design:
- Test on mobile (375px)
- Test on desktop (1200px+)
- Components stack properly
Quick Fixes
If something doesn’t work:
// Check console for errors
// Verify imports are correct
// Check component props match PropTypes
// Test mock API functions individuallyPart 6: Documentation & Reflection
This is a good practice to document your code.
Create README.md
# Review Aggregator Frontend
React frontend for Multi-Source Product Review Aggregator.
## Components
- **ReviewCard** - Individual review display
- **ReviewStats** - Aggregate statistics with charts
- **ReviewList** - Filtered list of reviews
- **ReviewFetcher** - Fetch new reviews button
- **ProductHeader** - Product information display
## Mock API
Located in `src/services/mockReviewAPI.js`
- Simulates backend endpoints
- Includes realistic delays
- 15+ sample reviews
## Features
✅ Fetch reviews on demand
✅ Display aggregate statistics
✅ Filter by source and rating
✅ Responsive design
✅ Loading and error states
✅ Accessible components
## Next Steps
- Replace mock API with real backend endpoints
- Add pagination for large review sets
- Implement review submission form
- Add real-time updatesReflection Questions
Consider these questions:
- React Patterns: How did you manage state across components?
- Component Design: Which components were easiest/hardest to build?
- AI Assistance: What worked well with AI prompts? What needed manual fixes?
- User Experience: How does the app feel to use? What would improve it?
- Code Organization: Is the component structure clear and maintainable?
Deliverables
Required files: - src/components/reviews/ReviewCard.jsx - src/components/reviews/ReviewStats.jsx - src/components/reviews/ReviewList.jsx - src/components/reviews/ReviewFetcher.jsx - src/components/reviews/ProductHeader.jsx - src/components/reviews/ReviewAggregatorPage.jsx - src/services/mockReviewAPI.js - README.md
Testing checklist: - [ ] All components render without errors - [ ] Fetch button loads new reviews - [ ] Filtering works correctly - [ ] Stats update after fetch - [ ] Responsive on mobile and desktop - [ ] Loading states display properly - [ ] Error handling works - [ ] No console warnings
Extension Challenges (Optional)
Challenge 1: Add Sorting
Add sorting options to ReviewList: - Sort by date (newest/oldest) - Sort by rating (highest/lowest) - Sort by source (alphabetical)
Challenge 2: Pagination
Implement pagination for reviews: - Show 10 reviews per page - Add page navigation - “Load more” button option
Challenge 3: Search
Add search functionality: - Search in review title and content - Highlight matching text - Debounced input for performance
Challenge 4: Enhanced Stats
Improve the statistics display: - Add trend indicators (↑↓) - Show rating distribution chart - Add sentiment analysis indicators
🎉 Practice Complete!
Congratulations! You’ve built a complete React frontend with:
- ✅ Interactive components with state management
- ✅ Mock API integration with async data fetching
- ✅ Responsive design with Tailwind CSS
- ✅ Proper component architecture
- ✅ Loading states and error handling
- ✅ Filtering and statistics display
You’re ready for the backend! 🚀