Connecting the React World: Component Communication

Discover how data flows through your app. Master props, callbacks, state lifting, and the Context API to build powerful, interconnected components.

Lesson ProgressStep 1 of 8
Parent
message: "Hello from Parent!"
⬇️ props
Child
Receives: "..."
0 EXP

Welcome! React apps are made of components. Let's see how they talk to each other.

// Two separate components... for now.

Props: The One-Way Street

The most fundamental way to communicate in React is from a parent component to a child component. This is done using **props** (short for "properties").

Think of it like this: a parent component holds some data (in its state or just as a variable) and passes it to its child as an attribute in the JSX.

// Parent
const parentMessage = "Hello Child!";
return <Child message={parentMessage} />;

// Child
function Child(props) {
  return <p>{props.message}</p>; // "Hello Child!"
}

Key points about props:

  • Data flows in **one direction** (unidirectional): from parent to child.
  • Props are **read-only**. A child component must never modify its own props.
  • You can pass any JavaScript value as a prop: strings, numbers, arrays, objects, and even functions.

System Check

A child component receives a prop called `count`. Can the child change this prop directly (e.g., `props.count = 10`)?

Advanced Holo-Simulations

0 EXP

Log in to unlock these advanced training modules and test your skills.


Achievements

🏆
Props Master

Successfully pass props from a parent to a child component.

🏗️
State Architect

Correctly identify the pattern for lifting state up.

Callback Wizard

Use a callback function to send data from child to parent.

Mission: Connect Parent and Child

Your goal: Make the `Parent` component manage a `count` state. Pass the `count` and the `setCount` function to the `Child`. The `Child` must display the count and be able to increment it.

A.D.A. Feedback:

> System integrity looks stable. Code is valid.

Challenge: The "Lifting State Up" Pattern

Two sibling components need to share the same state. Drag the steps into the correct order.

Pass state down to both siblings via props.
Identify the closest common ancestor (parent) of the siblings.
Pass handler functions down to update the state.
Move the shared state into the common parent.

Challenge: Complete the Prop Flow

Fill in the missing parts to pass and receive the `username` prop.

function App() {
  return <Welcome="Ada" />
}

function Welcome(username) {
  return <h1>Hello, {username}</h1>
}

Consult A.D.A.

Community Holo-Net

Peer Project Review

Submit your "Parent-Child Counter" project for feedback from other Net-Runners.

The Flow of Data: A Deep Dive into React Component Communication

A React application is a tree of components. For an application to be useful, these components must be able to "talk" to each other. This communication—the flow of data—is the most critical concept to master after learning what a component is. Data in React primarily flows in one direction: **down**, from parent to child.

1. The Primary Highway: Props (Parent-to-Child)

The most common and straightforward way to pass data is from a parent component to a child component using **props** (short for "properties"). Props are a read-only object of data passed to the child.

The parent passes data as attributes on the child component, just like HTML attributes. The child receives this data in an object called `props`.

// Parent Component
function App() {
  return <UserProfile username="Ada" age={28} />;
}

// Child Component
function UserProfile(props) {
  // props is { username: "Ada", age: 28 }
  return (
    <p>User: {props.username}, Age: {props.age}</p>
  );
}

A modern and cleaner way to use props is by **destructuring** them in the child's function signature:

// Child Component (Destructured)
function UserProfile({ username, age }) {
  return (
    <p>User: {username}, Age: {age}</p>
  );
}

You can pass any JavaScript value as a prop: strings, numbers, booleans, arrays, objects, and even functions. A special prop is props.children, which contains whatever content is nested *inside* the component's tags.

2. The Return Trip: Callbacks (Child-to-Parent)

Since data only flows down, how does a child send information back up? It can't. Instead, the parent passes a **function** down as a prop. The child can then *call* this function, passing data as an argument.

This is known as the **callback pattern**. The parent "hands the child a phone" (the function) and says, "Call me on this if anything happens."

// Parent Component
function SearchPage() {
  const [searchTerm, setSearchTerm] = useState('');

  // 1. Parent defines the function
  const handleSearch = (term) => {
    setSearchTerm(term);
  }

  return (
    <div>
      {/* 2. Parent passes the function as a prop */}
      <SearchBar onSearch={handleSearch} />
      <p>Searching for: {searchTerm}</p>
    </div>
  );
}

// Child Component
function SearchBar({ onSearch }) {
  const [input, setInput] = useState('');

  const handleChange = (e) => {
    setInput(e.target.value);
    // 3. Child calls the function from props
    onSearch(e.target.value);
  }

  return <input value={input} onChange={handleChange} />;
}

3. Sibling Rivalry: Lifting State Up

What if two sibling components need to share or react to the same state? They can't talk to each other directly. The solution is to **lift state up**.

You find their closest common ancestor (parent) and move the shared state into that parent. The parent then becomes the "single source of truth" and passes the state *down* to both siblings as props.

❌ Bad Practice

SiblingA has its own state. SiblingB has its own state. They are out of sync.

✔️ Good Practice

CommonParent holds the state. It passes the state to SiblingA and SiblingB, and passes a function to update the state.

4. The Global Broadcast: The Context API

Sometimes, you have data that many components need, at different nesting levels (e.g., user authentication, theme). Passing this data through every single intermediate component is called **"prop drilling"** and it's tedious and makes code hard to maintain.

The **Context API** is React's built-in solution. It allows a parent component to make data available to any component in its tree below it, without passing props manually.

  1. Create Context: const MyContext = React.createContext();
  2. Provide Value: Wrap your component tree with <MyContext.Provider value={...}>
  3. Consume Value: Any child component can use the useContext(MyContext) hook to read the value.
Key Takeaway: Start with props and callbacks. When you find siblings needing the same data, lift state up. If you find yourself "prop drilling," reach for the Context API.

React Communication Glossary

Component
A self-contained, reusable piece of UI. In React, components are functions or classes that return JSX.
Props (Properties)
A read-only object of data passed from a parent component to a child component to customize its behavior and output.
State
Data that is managed *within* a component. When state changes, the component re-renders to reflect the new data. Created with the `useState` hook.
One-Way Data Flow
The core principle in React where data (state) flows in a single direction: down the component tree from parents to children via props.
Callback Function
A function passed as a prop from a parent to a child. The child invokes this function (usually on a user event) to communicate data or an event back *up* to the parent.
Lifting State Up
A pattern for sharing state between sibling components. The shared state is moved to their closest common ancestor, which then passes the state down to the siblings via props.
Prop Drilling
The process of passing props down through multiple layers of nested components, even if the intermediate components don't use the props. This is generally discouraged.
Context API
React's built-in solution to avoid prop drilling. It allows a `Provider` component to make data available to any `Consumer` component in its tree.
`useContext`
The React hook used to "consume" or read a value from a Context Provider, subscribing the component to any changes in that value.
State Management Library
External libraries (like Redux, Zustand, or Jotai) used for managing complex, application-wide "global" state that is shared by many unrelated components.

About the Author

Author's Avatar

TodoTutorial Team

Passionate developers and educators making programming accessible to everyone.

This article was written and reviewed by our team of senior React developers, who use these patterns daily to build large-scale, maintainable applications.

Verification and Updates

Last reviewed: October 2025.

We strive to keep our content accurate and up-to-date. This tutorial is based on the latest React (v18+) specifications and hook-based patterns.

External Resources

Found an error or have a suggestion? Contact us!