Build real-world React projects including e-commerce, social media, and portfolio applications. Learn industry best practices and deployment strategies.
Build real-world React projects including e-commerce, social media, and portfolio applications. Learn industry best practices and deployment strategies.
Build a complete e-commerce application with product catalog, shopping cart, and checkout functionality
Content by: Himanshu Dabhi
MERN Stack Developer
Create a full-featured e-commerce application with product management, user authentication, shopping cart, and payment integration.
// E-commerce app structure
src/
├── components/
│ ├── layout/
│ │ ├── Header.js
│ │ ├── Footer.js
│ │ └── Navigation.js
│ ├── product/
│ │ ├── ProductCard.js
│ │ ├── ProductList.js
│ │ ├── ProductDetail.js
│ │ └── ProductFilter.js
│ ├── cart/
│ │ ├── CartItem.js
│ │ ├── CartSummary.js
│ │ └── CartDrawer.js
│ ├── auth/
│ │ ├── LoginForm.js
│ │ ├── RegisterForm.js
│ │ └── UserProfile.js
│ └── checkout/
│ ├── CheckoutForm.js
│ ├── OrderSummary.js
│ └── PaymentForm.js
├── pages/
│ ├── Home.js
│ ├── Products.js
│ ├── ProductDetail.js
│ ├── Cart.js
│ ├── Checkout.js
│ ├── Login.js
│ └── Profile.js
├── hooks/
│ ├── useCart.js
│ ├── useAuth.js
│ └── useProducts.js
├── context/
│ ├── CartContext.js
│ ├── AuthContext.js
│ └── ProductContext.js
├── utils/
│ ├── api.js
│ ├── validation.js
│ └── helpers.js
└── styles/
├── globals.css
└── components.css
// Product management with React Query
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
// Product hooks
function useProducts(filters = {}) {
return useQuery({
queryKey: ['products', filters],
queryFn: async () => {
const params = new URLSearchParams(filters);
const response = await fetch(`/api/products?${params}`);
return response.json();
},
});
}
function useProduct(productId) {
return useQuery({
queryKey: ['product', productId],
queryFn: async () => {
const response = await fetch(`/api/products/${productId}`);
return response.json();
},
enabled: !!productId,
});
}
// Shopping cart with Context API
import { createContext, useContext, useReducer } from 'react';
const CartContext = createContext();
const cartReducer = (state, action) => {
switch (action.type) {
case 'ADD_ITEM':
const existingItem = state.items.find(item => item.id === action.payload.id);
if (existingItem) {
return {
...state,
items: state.items.map(item =>
item.id === action.payload.id
? { ...item, quantity: item.quantity + 1 }
: item
)
};
}
return {
...state,
items: [...state.items, { ...action.payload, quantity: 1 }]
};
case 'REMOVE_ITEM':
return {
...state,
items: state.items.filter(item => item.id !== action.payload)
};
case 'UPDATE_QUANTITY':
return {
...state,
items: state.items.map(item =>
item.id === action.payload.id
? { ...item, quantity: action.payload.quantity }
: item
)
};
case 'CLEAR_CART':
return { ...state, items: [] };
default:
return state;
}
};
function CartProvider({ children }) {
const [state, dispatch] = useReducer(cartReducer, { items: [] });
const addItem = (product) => {
dispatch({ type: 'ADD_ITEM', payload: product });
};
const removeItem = (productId) => {
dispatch({ type: 'REMOVE_ITEM', payload: productId });
};
const updateQuantity = (productId, quantity) => {
dispatch({ type: 'UPDATE_QUANTITY', payload: { id: productId, quantity } });
};
const clearCart = () => {
dispatch({ type: 'CLEAR_CART' });
};
const getTotal = () => {
return state.items.reduce((total, item) => total + (item.price * item.quantity), 0);
};
const getItemCount = () => {
return state.items.reduce((count, item) => count + item.quantity, 0);
};
return (
<CartContext.Provider value={{
items: state.items,
addItem,
removeItem,
updateQuantity,
clearCart,
getTotal,
getItemCount
}}>
{children}
</CartContext.Provider>
);
}
function useCart() {
const context = useContext(CartContext);
if (!context) {
throw new Error('useCart must be used within a CartProvider');
}
return context;
}
// Product components
function ProductCard({ product }) {
const { addItem } = useCart();
return (
<div className="product-card">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p className="price">{product.price}</p>
<p className="description">{product.description}</p>
<button onClick={() => addItem(product)}>
Add to Cart
</button>
</div>
);
}
function ProductList({ filters }) {
const { data: products, isLoading, error } = useProducts(filters);
if (isLoading) return <div>Loading products...</div>;
if (error) return <div>Error loading products</div>;
return (
<div className="product-grid">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
// Cart components
function CartDrawer({ isOpen, onClose }) {
const { items, removeItem, updateQuantity, getTotal } = useCart();
return (
<div className={`cart-drawer ${isOpen ? 'open' : ''}`}>
<div className="cart-header">
<h2>Shopping Cart</h2>
<button onClick={onClose}>×</button>
</div>
<div className="cart-items">
{items.map(item => (
<CartItem
key={item.id}
item={item}
onRemove={() => removeItem(item.id)}
onUpdateQuantity={(quantity) => updateQuantity(item.id, quantity)}
/>
))}
</div>
<div className="cart-footer">
<div className="cart-total">
<strong>Total: {getTotal().toFixed(2)}</strong>
</div>
<button className="checkout-btn">Proceed to Checkout</button>
</div>
</div>
);
}
function CartItem({ item, onRemove, onUpdateQuantity }) {
return (
<div className="cart-item">
<img src={item.image} alt={item.name} />
<div className="item-details">
<h4>{item.name}</h4>
<p>{item.price}</p>
<div className="quantity-controls">
<button onClick={() => onUpdateQuantity(item.quantity - 1)}>-</button>
<span>{item.quantity}</span>
<button onClick={() => onUpdateQuantity(item.quantity + 1)}>+</button>
</div>
</div>
<button onClick={onRemove} className="remove-btn">Remove</button>
</div>
);
}
Test your understanding of this topic:
Build a social media platform with posts, comments, user profiles, and real-time features
Content by: Ashish Zapadiya
MERN Stack Developer
Create a social media platform with user authentication, posts, comments, likes, user profiles, and real-time notifications.
// Social media app features
- User authentication and profiles
- Create, edit, and delete posts
- Like and comment on posts
- Follow/unfollow users
- Real-time notifications
- News feed with infinite scroll
- User search and discovery
- Direct messaging
- Post sharing and bookmarking
// Main components structure
src/
├── components/
│ ├── auth/
│ │ ├── LoginModal.js
│ │ ├── RegisterModal.js
│ │ └── AuthGuard.js
│ ├── post/
│ │ ├── PostCard.js
│ │ ├── PostForm.js
│ │ ├── PostDetail.js
│ │ ├── CommentList.js
│ │ └── LikeButton.js
│ ├── profile/
│ │ ├── ProfileHeader.js
│ │ ├── ProfilePosts.js
│ │ ├── ProfileStats.js
│ │ └── EditProfile.js
│ ├── feed/
│ │ ├── NewsFeed.js
│ │ ├── FeedFilter.js
│ │ └── InfiniteScroll.js
│ └── common/
│ ├── Header.js
│ ├── Sidebar.js
│ ├── NotificationBell.js
│ └── SearchBar.js
├── hooks/
│ ├── usePosts.js
│ ├── useAuth.js
│ ├── useInfiniteScroll.js
│ └── useNotifications.js
├── context/
│ ├── AuthContext.js
│ ├── PostContext.js
│ └── NotificationContext.js
└── utils/
├── api.js
├── socket.js
└── helpers.js
// Real-time features with WebSocket
import { useEffect, useState } from 'react';
import io from 'socket.io-client';
// WebSocket connection
const socket = io('http://localhost:3001');
// Real-time notifications
function useNotifications() {
const [notifications, setNotifications] = useState([]);
useEffect(() => {
socket.on('notification', (notification) => {
setNotifications(prev => [notification, ...prev]);
});
socket.on('like', (data) => {
// Handle real-time like updates
console.log('Post liked:', data);
});
socket.on('comment', (data) => {
// Handle real-time comment updates
console.log('New comment:', data);
});
return () => {
socket.off('notification');
socket.off('like');
socket.off('comment');
};
}, []);
return { notifications };
}
// Post management with real-time updates
function usePosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
// Listen for real-time post updates
socket.on('newPost', (post) => {
setPosts(prev => [post, ...prev]);
});
socket.on('postUpdate', (updatedPost) => {
setPosts(prev => prev.map(post =>
post.id === updatedPost.id ? updatedPost : post
));
});
socket.on('postDelete', (postId) => {
setPosts(prev => prev.filter(post => post.id !== postId));
});
return () => {
socket.off('newPost');
socket.off('postUpdate');
socket.off('postDelete');
};
}, []);
const createPost = async (postData) => {
setLoading(true);
try {
const response = await fetch('/api/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(postData),
});
const newPost = await response.json();
// Emit real-time update
socket.emit('createPost', newPost);
setPosts(prev => [newPost, ...prev]);
} catch (error) {
console.error('Error creating post:', error);
} finally {
setLoading(false);
}
};
const likePost = async (postId) => {
try {
await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
socket.emit('likePost', { postId });
} catch (error) {
console.error('Error liking post:', error);
}
};
return { posts, loading, createPost, likePost };
}
// Post components
function PostCard({ post }) {
const { likePost } = usePosts();
const [liked, setLiked] = useState(post.liked);
const [likeCount, setLikeCount] = useState(post.likeCount);
const handleLike = async () => {
await likePost(post.id);
setLiked(!liked);
setLikeCount(prev => liked ? prev - 1 : prev + 1);
};
return (
<div className="post-card">
<div className="post-header">
<img src={post.author.avatar} alt={post.author.name} />
<div>
<h4>{post.author.name}</h4>
<span>{new Date(post.createdAt).toLocaleDateString()}</span>
</div>
</div>
<div className="post-content">
<p>{post.content}</p>
{post.image && <img src={post.image} alt="Post" />}
</div>
<div className="post-actions">
<button
onClick={handleLike}
className={`like-btn ${liked ? 'liked' : ''}`}
>
❤️ {likeCount}
</button>
<button className="comment-btn">💬 {post.commentCount}</button>
<button className="share-btn">📤 Share</button>
</div>
</div>
);
}
// Infinite scroll feed
function NewsFeed() {
const { posts, loading } = usePosts();
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);
const loadMorePosts = async () => {
if (loading || !hasMore) return;
try {
const response = await fetch(`/api/posts?page=${page + 1}`);
const newPosts = await response.json();
if (newPosts.length === 0) {
setHasMore(false);
} else {
setPosts(prev => [...prev, ...newPosts]);
setPage(prev => prev + 1);
}
} catch (error) {
console.error('Error loading more posts:', error);
}
};
useEffect(() => {
const handleScroll = () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 1000) {
loadMorePosts();
}
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [page, hasMore, loading]);
return (
<div className="news-feed">
{posts.map(post => (
<PostCard key={post.id} post={post} />
))}
{loading && <div className="loading">Loading more posts...</div>}
{!hasMore && <div className="end">No more posts to load</div>}
</div>
);
}
Test your understanding of this topic:
Create a professional portfolio website with animations, responsive design, and modern UI/UX
Content by: Bhavin Vora
React.js Developer
// Portfolio website features
- Responsive design
- Smooth animations
- Project showcase
- Skills and experience
- Contact form
- Blog section
- Dark/light theme
- SEO optimization
- Performance optimization
// Portfolio structure
src/
├── components/
│ ├── layout/
│ │ ├── Header.js
│ │ ├── Footer.js
│ │ └── Navigation.js
│ ├── sections/
│ │ ├── Hero.js
│ │ ├── About.js
│ │ ├── Skills.js
│ │ ├── Projects.js
│ │ ├── Experience.js
│ │ ├── Contact.js
│ │ └── Blog.js
│ ├── ui/
│ │ ├── Button.js
│ │ ├── Card.js
│ │ ├── Modal.js
│ │ └── ThemeToggle.js
│ └── animations/
│ ├── FadeIn.js
│ ├── SlideIn.js
│ └── Parallax.js
├── pages/
│ ├── Home.js
│ ├── About.js
│ ├── Projects.js
│ ├── Blog.js
│ └── Contact.js
├── hooks/
│ ├── useScrollPosition.js
│ ├── useTheme.js
│ └── useIntersectionObserver.js
├── data/
│ ├── projects.js
│ ├── skills.js
│ ├── experience.js
│ └── blog-posts.js
└── styles/
├── globals.css
├── components.css
└── animations.css
// Modern portfolio components
import { motion } from 'framer-motion';
import { useState, useEffect } from 'react';
// Hero section with animations
function Hero() {
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const handleMouseMove = (e) => {
setMousePosition({ x: e.clientX, y: e.clientY });
};
window.addEventListener('mousemove', handleMouseMove);
return () => window.removeEventListener('mousemove', handleMouseMove);
}, []);
return (
<motion.section
className="hero"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1 }}
>
<motion.div
className="hero-content"
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8, delay: 0.2 }}
>
<motion.h1
initial={{ scale: 0.8 }}
animate={{ scale: 1 }}
transition={{ duration: 0.5, delay: 0.5 }}
>
Hi, I'm <span className="highlight">Your Name</span>
</motion.h1>
<motion.p
initial={{ y: 50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8, delay: 0.7 }}
>
Full-Stack Developer & UI/UX Designer
</motion.p>
<motion.div
className="hero-buttons"
initial={{ y: 50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8, delay: 0.9 }}
>
<Button variant="primary">View Projects</Button>
<Button variant="secondary">Contact Me</Button>
</motion.div>
</motion.div>
<motion.div
className="floating-elements"
animate={{
x: mousePosition.x * 0.01,
y: mousePosition.y * 0.01,
}}
transition={{ type: "spring", stiffness: 50 }}
>
<div className="floating-shape shape-1"></div>
<div className="floating-shape shape-2"></div>
<div className="floating-shape shape-3"></div>
</motion.div>
</motion.section>
);
}
// Project showcase with filters
function Projects() {
const [filter, setFilter] = useState('all');
const [projects, setProjects] = useState([]);
const categories = ['all', 'web', 'mobile', 'design', 'other'];
const filteredProjects = projects.filter(project =>
filter === 'all' || project.category === filter
);
return (
<section className="projects">
<motion.h2
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
My Projects
</motion.h2>
<div className="filter-buttons">
{categories.map(category => (
<motion.button
key={category}
onClick={() => setFilter(category)}
className={`filter-btn ${filter === category ? 'active' : ''}`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
{category.charAt(0).toUpperCase() + category.slice(1)}
</motion.button>
))}
</div>
<motion.div
className="projects-grid"
layout
>
{filteredProjects.map((project, index) => (
<motion.div
key={project.id}
layout
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.3, delay: index * 0.1 }}
whileHover={{ y: -10 }}
>
<ProjectCard project={project} />
</motion.div>
))}
</motion.div>
</section>
);
}
// Project card component
function ProjectCard({ project }) {
const [isHovered, setIsHovered] = useState(false);
return (
<motion.div
className="project-card"
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
whileHover={{ scale: 1.02 }}
>
<div className="project-image">
<img src={project.image} alt={project.title} />
<motion.div
className="project-overlay"
initial={{ opacity: 0 }}
animate={{ opacity: isHovered ? 1 : 0 }}
transition={{ duration: 0.3 }}
>
<div className="project-links">
<a href={project.liveUrl} target="_blank" rel="noopener">
Live Demo
</a>
<a href={project.githubUrl} target="_blank" rel="noopener">
GitHub
</a>
</div>
</motion.div>
</div>
<div className="project-content">
<h3>{project.title}</h3>
<p>{project.description}</p>
<div className="project-tech">
{project.technologies.map(tech => (
<span key={tech} className="tech-tag">{tech}</span>
))}
</div>
</div>
</motion.div>
);
}
// Skills section with progress bars
function Skills() {
const skills = [
{ name: 'React', level: 90 },
{ name: 'JavaScript', level: 85 },
{ name: 'Node.js', level: 80 },
{ name: 'Python', level: 75 },
{ name: 'CSS/SASS', level: 88 },
{ name: 'TypeScript', level: 70 },
];
return (
<section className="skills">
<motion.h2
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
Skills & Technologies
</motion.h2>
<div className="skills-grid">
{skills.map((skill, index) => (
<motion.div
key={skill.name}
className="skill-item"
initial={{ opacity: 0, x: -50 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<div className="skill-header">
<h3>{skill.name}</h3>
<span>{skill.level}%</span>
</div>
<div className="skill-bar">
<motion.div
className="skill-progress"
initial={{ width: 0 }}
whileInView={{ width: `${skill.level}%` }}
transition={{ duration: 1, delay: 0.2 }}
/>
</div>
</motion.div>
))}
</div>
</section>
);
}
Test your understanding of this topic:
Learn deployment strategies, performance optimization, and best practices for production React applications
Content by: Dharmik Tank
MERN Stack Developer
// Deployment options for React apps
1. Vercel (Recommended for React)
2. Netlify
3. AWS Amplify
4. Firebase Hosting
5. GitHub Pages
6. Docker + Cloud Platforms
// Vercel deployment
npm install -g vercel
// vercel.json configuration
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": { "distDir": "build" }
}
],
"routes": [
{
"src": "/static/(.*)",
"dest": "/static/$1"
},
{
"src": "/(.*)",
"dest": "/index.html"
}
],
"env": {
"REACT_APP_API_URL": "https://your-api.com"
}
}
// Netlify deployment
// netlify.toml
[build]
command = "npm run build"
publish = "build"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
// Environment variables
// .env.production
REACT_APP_API_URL=https://api.production.com
REACT_APP_GA_TRACKING_ID=GA-XXXXXXXXX
REACT_APP_SENTRY_DSN=https://xxxxx@sentry.io/xxxxx
// Performance optimization
// 1. Code splitting
import { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
// 2. Image optimization
import { LazyLoadImage } from 'react-lazy-load-image-component';
function OptimizedImage({ src, alt }) {
return (
<LazyLoadImage
src={src}
alt={alt}
effect="blur"
placeholderSrc="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k="
/>
);
}
// 3. Bundle analysis
npm install --save-dev webpack-bundle-analyzer
// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
};
// 4. Service Worker for PWA
// public/sw.js
const CACHE_NAME = 'my-app-v1';
const urlsToCache = [
'/',
'/static/js/bundle.js',
'/static/css/main.css',
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
// 5. SEO optimization
// public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Your app description" />
<meta name="keywords" content="react, javascript, web development" />
<meta name="author" content="Your Name" />
<!-- Open Graph -->
<meta property="og:title" content="Your App Title" />
<meta property="og:description" content="Your app description" />
<meta property="og:image" content="%PUBLIC_URL%/og-image.jpg" />
<meta property="og:url" content="https://yourapp.com" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Your App Title" />
<meta name="twitter:description" content="Your app description" />
<meta name="twitter:image" content="%PUBLIC_URL%/og-image.jpg" />
<title>Your App Title</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
// Performance monitoring and analytics
// 1. React Profiler
import { Profiler } from 'react';
function onRenderCallback(
id, // the "id" prop of the Profiler tree that has just committed
phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered)
actualDuration, // time spent rendering the committed update
baseDuration, // estimated time to render the entire subtree without memoization
startTime, // when React began rendering this update
commitTime, // when React committed this update
interactions // the Set of interactions belonging to this update
) {
console.log(`Component ${id} took ${actualDuration}ms to render`);
}
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<YourApp />
</Profiler>
);
}
// 2. Performance monitoring with Sentry
import * as Sentry from "@sentry/react";
Sentry.init({
dsn: process.env.REACT_APP_SENTRY_DSN,
environment: process.env.NODE_ENV,
integrations: [
new Sentry.BrowserTracing(),
],
tracesSampleRate: 1.0,
});
// 3. Google Analytics
import ReactGA from 'react-ga';
ReactGA.initialize(process.env.REACT_APP_GA_TRACKING_ID);
function App() {
useEffect(() => {
ReactGA.pageview(window.location.pathname);
}, []);
return <YourApp />;
}
// 4. Custom performance hooks
function usePerformanceMonitor(componentName) {
useEffect(() => {
const startTime = performance.now();
return () => {
const endTime = performance.now();
const duration = endTime - startTime;
if (duration > 100) {
console.warn(`${componentName} took ${duration.toFixed(2)}ms to render`);
}
};
});
}
// 5. Error boundaries with monitoring
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
Sentry.captureException(error, { extra: errorInfo });
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
// 6. Bundle size monitoring
// package.json
{
"scripts": {
"analyze": "npm run build && npx webpack-bundle-analyzer build/static/js/*.js",
"build:analyze": "GENERATE_SOURCEMAP=false npm run build && npx webpack-bundle-analyzer build/static/js/*.js"
}
}
// 7. Lighthouse CI
// .lighthouserc.js
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000'],
startServerCommand: 'npm start',
},
assert: {
assertions: {
'categories:performance': ['warn', { minScore: 0.8 }],
'categories:accessibility': ['error', { minScore: 0.9 }],
'categories:best-practices': ['warn', { minScore: 0.8 }],
'categories:seo': ['warn', { minScore: 0.8 }],
},
},
upload: {
target: 'temporary-public-storage',
},
},
};
Test your understanding of this topic:
Continue your learning journey and master the next set of concepts.
Back to Course Overview