6. Components & Props

Chapter 6: React Components & Props

Components are the foundational atoms of React applications, while props represent the immutable contracts that connect them. Learn how to author pure functional components, destructure props cleanly, leverage component composition, and write modular, maintainable frontend architectures.

1. What is a React Component?

In React, a component is an independent, reusable piece of code that defines how a section of the user interface should appear and behave. Rather than mixing presentation and behavior arbitrarily across large files, components encapsulate their own structure (JSX), styling (CSS/Modules), and state logic into a unified building block.

Functional Components (The Modern Standard):

A modern React component is simply a JavaScript function that accepts an optional props object as its parameter and returns React elements (JSX):

// A pure functional component
function UserBadge(props) {
  return (
    <div className="badge-container">
      <img src={props.avatarUrl} alt={props.username} />
      <span>{props.username}</span>
    </div>
  );
}

export default UserBadge;
💡 The Naming Rule for React Components

Component names MUST always start with a capital letter (e.g., UserBadge, not userBadge). React treats lowercase tags (like <div>, <span>) as native HTML elements. Uppercase tags indicate custom React components that must be compiled into function calls.

2. Functional Components vs. Legacy Class Components

Before React 16.8 (2019), components requiring state or lifecycle methods had to be written as ES6 Classes. Today, functional components paired with Hooks have rendered class components obsolete. Understanding the comparison is still crucial when maintaining enterprise codebases:

FeatureModern Functional ComponentsLegacy Class Components
SyntaxPlain JavaScript function returning JSX.ES6 class extending React.Component with a render() method.
State ManagementHooks (useState, useReducer).this.state object and this.setState().
Lifecycle ExecutionSynchronized via useEffect.Divided into componentDidMount, componentDidUpdate, etc.
`this` BindingNo this keyword; avoids scoping bugs.Requires manual binding of event handlers in constructor.
Bundle OptimizationMinifies better; superior tree-shaking support.Larger bundle size due to prototype chain boilerplate.

3. Understanding Props & Destructuring

Props (short for properties) are inputs passed from a parent component down to a child component. Props are strictly read-only. A component must never mutate the props it receives!

Clean Parameter Destructuring & Default Values:

Instead of accessing props.title and props.price repeatedly, clean modern code destructures properties directly inside the function signature:

// Clean destructuring with default fallback values
function ProductCard({ 
  title, 
  price, 
  category = "General", 
  inStock = true, 
  onAddToCart 
}) {
  return (
    <article className="product-card">
      <span className="category-pill">{category}</span>
      <h3>{title}</h3>
      <p className="price">${price.toFixed(2)}</p>
      
      {inStock ? (
        <button onClick={onAddToCart} className="btn-buy">
          Add to Cart
        </button>
      ) : (
        <span className="out-of-stock">Sold Out</span>
      )}
    </article>
  );
}
⚠️ Pure Functions: Why Props Must Remain Immutable

In computer science, a pure function does not change any objects or variables that existed before it was called, and given the same inputs, it always returns the exact same result.React requires all components to act as pure functions with respect to their props.Never write props.price = 100; if data must change, use State instead!

4. The `children` Prop & Component Composition

Sometimes a component cannot know its children ahead of time (for example, generic containers like dialogs, sidebars, or cards). React provides the special children prop to pass nested JSX directly through:

// 1. Generic Container Component
function ModalCard({ title, children }) {
  return (
    <div className="modal-backdrop">
      <div className="modal-card">
        <header className="modal-header">
          <h3>{title}</h3>
        </header>
        <div className="modal-body">
          {children} {/* Renders whatever is nested inside */}
        </div>
      </div>
    </div>
  );
}

// 2. Consuming Component
function ProfileSettings() {
  return (
    <ModalCard title="Account Settings">
      <p>Manage your password and security keys here.</p>
      <button className="btn-save">Update Password</button>
    </ModalCard>
  );
}

Composition vs. Inheritance:

In object-oriented programming, developers frequently create complex inheritance hierarchies (e.g., SpecialButton extends Button). In React, the Meta team strongly advocates Composition over Inheritance. Components can accept other components as props or nest them via children, making inheritance completely unnecessary.

5. The Prop Drilling Problem & Architectural Remedies

Prop drilling occurs when a piece of data needed by a deeply nested component must be threaded through several layers of intermediate parent components that have no use for that data:

Page (holds currentUser) →
Sidebar (does not need user) →
UserMenu (does not need user) →
Avatar (displays user photo)

How to Mitigate Prop Drilling:

  • Component Composition (Slot Pattern): Pass the child component directly as a prop (e.g., <Sidebar avatar={<Avatar user={user} />} />). Intermediate containers don't need to know what props the avatar requires!
  • React Context API: Broadcast global data (authentication, theme, language) directly across the component tree without manual passing.
  • Global State Stores: Use libraries like Zustand or Redux Toolkit for complex application state.

Frequently Asked Questions (FAQ)

Why are props immutable in React?

Props are strictly read-only to preserve component purity and maintain unidirectional data flow. If a child component were permitted to modify props directly, it would cause unpredictable side effects in the parent component and break React's ability to reason about and optimize the render tree.

What is the special 'children' prop in React?

The 'children' prop is an automatic prop passed to components that allows you to nest other components or JSX elements inside a component tag (e.g., <Card><p>Content</p></Card>). It enables the Component Composition pattern, making UI wrappers highly reusable.

What is the difference between Functional Components and Class Components?

Functional components are plain JavaScript functions that take props as an argument and return JSX; they manage state and side effects using Hooks. Class components extend React.Component, require a render() method, manage state via this.state and this.setState, and utilize class lifecycle methods. Modern React development exclusively favors functional components.

What is prop drilling and how do you resolve it?

Prop drilling occurs when you have to pass props down through multiple layers of intermediate components that do not actually need the data themselves, merely to reach a deeply nested child. You can resolve prop drilling using Component Composition, React Context API, or global state management libraries like Zustand or Redux.

Explore Related Tools

Hand-picked utilities and calculators related to this tool.

Related Tools