Component Communication

Building the shopping cart for my POS system taught me a crucial lesson: components don't exist in isolation. When a user clicks "Add to Cart" on a product card, the cart component needs to know about it. When the cart updates, the header showing the item count needs to reflect the change. This is component communicationβ€”the art of making components talk to each other.

I started by putting all state in every component. The cart had its own state, each product card had its own state, the header had its own state. Nothing was synchronized. The cart count showed 5, but the cart itself was empty. It was chaos. Then I learned: data flows down, events flow up.

The Fundamental Pattern: Props Down, Callbacks Up

This is the core of React's architecture:

  • Props carry data from parent to child (down the tree)

  • Callbacks carry events from child to parent (up the tree)

  • State lives in the parent that needs to coordinate children

In the POS system:

  • Parent (CheckoutPage) manages cart state

  • Child (ProductCard) receives product data via props

  • Child calls onAddToCart callback to notify parent

  • Parent updates state, all children re-render with new data

Props: Passing Data Down

We've seen props before, but let's understand them deeply.

Basic Props Example

Using it:

Data flows down: ProductList β†’ ProductCard

Props Are Read-Only

Why? Props belong to the parent. Only the parent should change them.

If you need to modify data:

Callbacks: Events Flow Up

Props go down. How do we send information back up? Callbacks.

Adding Products to Cart

Parent component:

Event flows up: ProductCard β†’ ProductList

Naming Convention

  • Props that are callbacks start with on: onAddToCart, onClick, onSubmit

  • Handler functions start with handle: handleAddToCart, handleClick, handleSubmit

Lifting State Up

Here's where it gets interesting. When two components need to share state, lift the state to their common parent.

Problem: Disconnected Components

These three components don't share state. Each has its own cart.

Solution: Lift State to Common Parent

Now all components share the same cart state through props and callbacks.

Building the Cart System

Let's build a complete, production-quality cart for the POS system.

The Parent Component (State Manager)

The ProductGrid Child Component

The Cart Child Component

Data flow:

  1. User clicks "Add to Cart" on ProductCard

  2. ProductCard calls onAddToCart(product)

  3. Callback bubbles up to CheckoutPage

  4. CheckoutPage updates cart state

  5. New cart state flows down as props to Cart

  6. Cart re-renders with new items

Sharing State Between Siblings

Components at the same level (siblings) can't pass data directly. They must communicate through a shared parent.

Problem: Cart Count in Header

The Header needs to show cart item count, but the cart is managed by CheckoutPage.

Solution: Lift cart state to App, the common parent. Now both children can access it.

Real Example: Search and Filter

In the POS, I have a search bar in the header and product grid in the body. They're siblings, but filtering needs to work.

How it works:

  1. State lives in App (common parent)

  2. Header receives current values and callbacks

  3. ProductGrid receives filtered results

  4. User types in search β†’ Header calls onSearchChange β†’ App updates state β†’ ProductGrid gets new filtered products

Prop Drilling: The Problem We'll Solve Next

As applications grow, passing props through many levels becomes tedious:

We're passing cart through 4 components just so CartBadge can use it. The middle components don't even care about cartβ€”they're just passing it along.

Solution: Context API (next article!)

Complete POS Checkout Flow

Here's the full working example showing all patterns together:

This demonstrates:

  • State lifted to parent (CheckoutPage)

  • Props flowing down to children

  • Callbacks flowing up from children

  • Sibling communication through parent

  • Derived state (filtered products, totals)

  • Multiple callbacks for different operations

Common Mistakes to Avoid

1. Not Lifting State High Enough

Fix: Lift cart state to parent of both components.

2. Passing Too Many Props

Fix: Group related props or use Context (next article).

3. Mutating Props

Fix: Create new values, don't mutate props.

4. Callback Hell

Fix: Extract to a named function in parent component.

Key Learnings

  1. Props flow down from parent to child

  2. Callbacks flow up from child to parent

  3. State should live in the lowest common ancestor

  4. Props are read-only - never mutate them

  5. Siblings communicate through their parent

  6. Derived state (calculated values) doesn't need useState

  7. Lift state up when multiple components need it

  8. Name callbacks with on prefix, handlers with handle prefix

Next Steps

You've mastered component communication, but passing props through many levels gets tedious. In the next article, we'll explore the Context APIβ€”React's built-in solution for sharing state globally without prop drilling. We'll use it to build cart and authentication contexts for the POS system.

Continue to: Context API β†’

Last updated