Practice 3 — React Review Aggregator Frontend

Build Interactive Product Review Interface with React

Practice
React
Frontend
Review Aggregator
Auteur
Affiliations

Université de Toulon

LIS UMR CNRS 7020

Date de publication

2025-10-16

Résumé

Course lectures and practices for JavaScript full‑stack web development with AI‑assisted workflows.

Note

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).

  1. Create the React app with Vite :
# This create the react app in the frontend directory
npm create vite@latest frontend -- --template react

you can start and open in your browser.

  1. Install dependencies and common helper libs:
# Install dependencies
# IN ANOTHER TERMINAL otherwise the app will stop
# PropTypes (used in exercises)
npm install prop-types
  1. If you stopped the server run it :
npm run dev
# Opens http://localhost:5173 by default

Where to paste the exercises

  • Create src/components/ and paste components there.
  • Use src/App.jsx to 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.

  1. 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.
  1. Customer with props
  • Goal: Convert the static component to accept props for name, email, and avatarUrl.
  • 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`.
  1. Customer with local state
  • Goal: Add a follow/unfollow button using useState so the component becomes interactive.
  • File: src/components/CustomerWithState.jsx
  • Instructions: Ask the AI to create the component with a following boolean state, a button toggling it, accessible labels, and simple Tailwind styles. Show how a parent App.jsx can 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.

  1. Customer controlled form
  • Goal: Create a controlled CustomerForm component that accepts name and email, validates them, and calls onSubmit with the values.
  • File: src/components/CustomerForm.jsx
  • Instructions: Use useState to manage inputs, show simple validation (required, email format), disable submit until valid, and call onSubmit({ 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

  1. Customer list & lifted state
  • Goal: Build CustomerList.jsx that receives an array of customers and renders CustomerWithState for each. Add UI to add new customers with the CustomerForm and keep the list in the parent using useState.
  • File: src/components/CustomerList.jsx
  • Instructions: The parent should contain the array state, pass onFollowChange down 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.

What You’ll Build

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

Astuce

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.1: Navigate to Frontend

# Make sure you're in the right place
cd fullstack-minimal-app/frontend

# Install dependencies if needed
npm install

# Start development server
npm run dev
# Opens http://localhost:5173

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.js

Your 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 file

Save 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 component

Test 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 component

Exercise 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 component

Exercise 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 component

Exercise 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 component

Exercise 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

  1. Initial Load:
    • Page loads with empty state
    • “Fetch Reviews” button is prominent
  2. Fetch Reviews:
    • Click fetch button
    • Loading state shows
    • After delay, reviews appear
    • Stats update with aggregated data
  3. Filtering:
    • Test source filter (All, Amazon, BestBuy, Walmart)
    • Test rating filter (All, 5★, 4★+, etc.)
    • Verify review count updates
  4. 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 individually

Part 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 updates

Reflection Questions

Consider these questions:

  1. React Patterns: How did you manage state across components?
  2. Component Design: Which components were easiest/hardest to build?
  3. AI Assistance: What worked well with AI prompts? What needed manual fixes?
  4. User Experience: How does the app feel to use? What would improve it?
  5. 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 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! 🚀

Réutilisation