Skip to Content
Module 2: React Fundamentals2.4 Component Anatomy

Module 2.4: Component Anatomy

Component Anatomy Banner

🎯 Learning Objectives

Upon completing this lesson, you will be able to:

  • Understand Function Components and why they are preferred.
  • Pass data using Props from a Parent to a Child Component.
  • Master the principle that Props are Read-only.
  • Utilize Destructuring Props for cleaner code.
  • Apply the Children Prop for the Composition pattern.
  • Analyze UI Designs into a Component Hierarchy.

1. Function Component vs Class Component

1.1. Two Types of Components

React supports two ways to define components:

Diagram showing Function and Class component types

Function Component (Recommended):

function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } // Or using an Arrow Function const Greeting = ({ name }) => { return <h1>Hello, {name}!</h1>; };

Class Component (Legacy):

import { Component } from 'react'; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}!</h1>; } }

1.2. Why Choose Function Components?

CriterionFunction ComponentClass Component
SyntaxConcise, easy to readVerbose, complex
Hooks✅ Full support❌ No support
this keywordNot requiredMust use this.props, this.state
PerformanceBetter (lighter)Heavier
React Team✅ Recommended⚠️ Legacy

💡 Key Takeaway: Since React 16.8+ (with Hooks), Function Components have become the standard. Class Components are now primarily found in older codebases.

1.3. Function Component Structure

// 1. Imports (if needed) import { useState } from 'react'; // 2. Component Function function ProductCard({ name, price, image }) { // 3. Logic (hooks, variables, functions) const formattedPrice = `$${price.toFixed(2)}`; // 4. Return JSX return ( <div className="product-card"> <img src={image} alt={name} /> <h3>{name}</h3> <p>{formattedPrice}</p> </div> ); } // 5. Export export default ProductCard;

2. Props - Passing Data

2.1. What are Props?

Props (Properties) are how you pass data from a Parent Component to a Child Component.

Diagram illustrating data flow from Parent to Child component via props

// Parent Component function App() { return ( <div> <UserCard name="Alice" age={25} isActive={true} /> <UserCard name="Bob" age={30} isActive={false} /> </div> ); } // Child Component function UserCard({ name, age, isActive }) { return ( <div className="user-card"> <h2>{name}</h2> <p>Age: {age}</p> <span>{isActive ? '🟢 Active' : '🔴 Inactive'}</span> </div> ); }

2.2. Prop Data Types

<Component // String title="Hello World" // Number count={42} price={99.99} // Boolean isVisible={true} disabled={false} // Array items={['Apple', 'Banana', 'Orange']} // Object user={{ name: 'Alice', email: 'alice@example.com' }} // Function onClick={() => console.log('Clicked!')} onSubmit={handleSubmit} // JSX / Component icon={<StarIcon />} />

2.3. The Props Object

All props are bundled into a single object:

function UserCard(props) { console.log(props); // { name: "Alice", age: 25, isActive: true } return ( <div> <h2>{props.name}</h2> <p>Age: {props.age}</p> </div> ); }

3. Props Are Read-Only

3.1. The Immutability Principle

Props cannot be modified inside a component. This embodies React’s one-way data flow principle.

// ❌ INCORRECT - Do not modify props directly function UserCard({ name }) { name = name.toUpperCase(); // Error! return <h2>{name}</h2>; } // ✅ CORRECT - Create a new variable from props function UserCard({ name }) { const displayName = name.toUpperCase(); return <h2>{displayName}</h2>; }

3.2. Why Should Props Be Immutable?

ReasonExplanation
PredictableA component always renders consistently with the same props.
DebuggingEasy to track data flow from parent to child.
PerformanceReact compares props to decide whether to re-render.
UnidirectionalData flows in one direction only: Parent → Child.

3.3. What If You Need to Change Data?

If you need to change data, use State (which we’ll cover in a later module):

// Parent manages state, passes it down to child via props function App() { const [count, setCount] = useState(0); return <Counter value={count} onIncrement={() => setCount(count + 1)} />; } function Counter({ value, onIncrement }) { return ( <div> <p>Count: {value}</p> <button onClick={onIncrement}>+1</button> </div> ); }

4. Destructuring Props

4.1. In Function Parameters

The most common approach is to destructure directly within the function parameter:

// ❌ Without destructuring - you have to write props.xxx multiple times function UserCard(props) { return ( <div> <h2>{props.name}</h2> <p>{props.email}</p> </div> ); } // ✅ Destructure in the parameter - cleaner function UserCard({ name, email }) { return ( <div> <h2>{name}</h2> <p>{email}</p> </div> ); }

4.2. Default Values

Set default values when props are not passed:

function Button({ label = 'Click me', variant = 'primary', size = 'medium', disabled = false }) { return ( <button className={`btn btn-${variant} btn-${size}`} disabled={disabled}> {label} </button> ); }
// Usage <Button /> // Uses all defaults <Button label="Submit" /> // Overrides label <Button variant="danger" size="lg"/> // Overrides variant & size

4.3. Rest Props

Capture remaining props using the spread operator:

function Input({ label, error, ...rest }) { return ( <div className="input-group"> <label>{label}</label> <input {...rest} /> {error && <span className="error">{error}</span>} </div> ); } // Usage - type, placeholder, and onChange are passed to the <input /> element <Input label="Email" type="email" placeholder="Enter email" onChange={handleChange} error={errors.email} />;

5. The Children Prop

5.1. What is Children?

children is a special prop that holds the content between a component’s opening and closing tags:

// Parent passes children <Card> <h2>Title</h2> <p>Content goes here</p> </Card>; // Card component receives children function Card({ children }) { return <div className="card">{children}</div>; }

5.2. Composition Pattern

Diagram illustrating how the children prop enables component composition

// Layout Component function PageLayout({ children }) { return ( <div className="page"> <Header /> <main className="content">{children}</main> <Footer /> </div> ); } // Usage function HomePage() { return ( <PageLayout> <h1>Welcome</h1> <p>This is the home page content.</p> <ProductList /> </PageLayout> ); }

5.3. Example: Modal Component

function Modal({ isOpen, onClose, title, children }) { if (!isOpen) return null; return ( <div className="modal-overlay" onClick={onClose}> <div className="modal" onClick={(e) => e.stopPropagation()}> <div className="modal-header"> <h2>{title}</h2> <button onClick={onClose}>×</button> </div> <div className="modal-body">{children}</div> </div> </div> ); } // Usage <Modal isOpen={showModal} onClose={() => setShowModal(false)} title="Confirm"> <p>Are you sure you want to delete this item?</p> <button onClick={handleDelete}>Delete</button> <button onClick={() => setShowModal(false)}>Cancel</button> </Modal>;

6. Product Mindset: Design → Components

6.1. Analyzing the UI

When you receive a design, here’s the mindset process:

  1. Look at the big picture → Identify the main layout
  2. Break it down → Find repeatable sections
  3. Name them → Give your components meaningful names
  4. Determine props → Identify what data needs to be passed in

6.2. Example: Product Card UI

Let’s say you have a design like this:

Visual design of a product card, showing image, name, rating, price, and add to cart button

Step 1: Identify Components

ProductCard ├── ProductImage ├── ProductInfo │ ├── ProductName │ ├── Rating │ └── Price └── AddToCartButton

Step 2: Determine Props

// What data does ProductCard need? interface ProductCardProps { id: string; name: string; image: string; rating: number; reviewCount: number; price: number; originalPrice?: number; onAddToCart: (id: string) => void; }

Step 3: Implement

function ProductCard({ id, name, image, rating, reviewCount, price, originalPrice, onAddToCart }) { return ( <div className="product-card"> <img src={image} alt={name} className="product-image" /> <div className="product-info"> <h3 className="product-name">{name}</h3> <Rating value={rating} count={reviewCount} /> <Price current={price} original={originalPrice} /> </div> <button onClick={() => onAddToCart(id)}>Add to Cart</button> </div> ); }

6.3. Component Hierarchy

Diagram illustrating a component hierarchy for a product listing page

7. References

Last updated on