Chapter 5: Frontend Development
Chapter 5 of 15
Chapter 5: Frontend Development
5.1 Component Architecture
Well-structured component architecture makes applications maintainable and scalable.
// Component structure
components/
ui/ # Reusable UI components
Button.jsx
Input.jsx
Modal.jsx
features/ # Feature-specific components
auth/
LoginForm.jsx
SignupForm.jsx
products/
ProductCard.jsx
ProductList.jsx
layout/ # Layout components
Header.jsx
Sidebar.jsx
Footer.jsx
5.2 Component Patterns
// Presentational component
function ProductCard({ product, onAddToCart }) {
return (
<div className="product-card">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p>${product.price}</p>
<button onClick={() => onAddToCart(product)}>
Add to Cart
</button>
</div>
);
}
// Container component
function ProductListContainer() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchProducts().then(data => {
setProducts(data);
setLoading(false);
});
}, []);
const handleAddToCart = (product) => {
// Add to cart logic
};
if (loading) return <div>Loading...</div>;
return (
<div className="product-list">
{products.map(product => (
<ProductCard
key={product.id}
product={product}
onAddToCart={handleAddToCart}
/>
))}
</div>
);
}
5.3 Form Handling
// Controlled components
function LoginForm() {
const [formData, setFormData] = useState({
email: "",
password: ""
});
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = async (e) => {
e.preventDefault();
await login(formData);
};
return (
<form onSubmit={handleSubmit}>
<input
name="email"
value={formData.email}
onChange={handleChange}
/>
<input
name="password"
type="password"
value={formData.password}
onChange={handleChange}
/>
<button type="submit">Login</button>
</form>
);
}