I have spent over eight years building complex React applications for various tech hubs across the US.
In my experience, understanding how data flows between components is the single most important skill for a React developer.
If you don’t get this right, your codebase will quickly become a tangled mess that is impossible to maintain.
In this tutorial, I will show you exactly how to handle parent-to-child and child-to-parent communication using practical, real-world examples.
How Parent-to-Child Communication Works in React
The most common way to send data in React is from a parent component down to its child.
We do this using “props,” which is short for properties. Think of props as arguments you pass to a function.
In my early days of React, I found it helpful to think of the parent as the “source of truth” and the child as the “presenter.”
Example: US Real Estate Listing
Let’s look at a practical example involving a real estate listing in San Francisco. We want to pass property details from the main dashboard to a display card.
import React from 'react';
// The Child Component
const PropertyCard = (props) => {
return (
<div style={{ border: '1px solid #ccc', padding: '20px', borderRadius: '8px' }}>
<h2>{props.address}</h2>
<p>City: {props.city}</p>
<p>Price: ${props.price.toLocaleString()}</p>
<p>Status: {props.isAvailable ? 'Active' : 'Sold'}</p>
</div>
);
};
// The Parent Component
const RealEstateDashboard = () => {
const propertyInfo = {
address: '101 Market St',
city: 'San Francisco, CA',
price: 1250000,
isAvailable: true
};
return (
<div style={{ padding: '40px' }}>
<h1>Current Listings</h1>
{/* Passing data via props */}
<PropertyCard
address={propertyInfo.address}
city={propertyInfo.city}
price={propertyInfo.price}
isAvailable={propertyInfo.isAvailable}
/>
</div>
);
};
export default RealEstateDashboard;You can refer to the screenshot below to see the output.

In this example, the RealEstateDashboard holds the data and passes it to PropertyCard. The child component is generic and simply displays whatever data it receives.
How Child-to-Parent Communication Works in React
Passing data back up to a parent is a bit different because props only flow one way (downwards).
To send data up, we pass a function from the parent to the child as a prop.
I often call these “callback props.” The child calls this function when something happens, like a button click.
Example: US Tax Filing Status Selector
Imagine a tax application where a user selects their filing status. The parent needs to know what the child selected to calculate the final tax.
import React, { useState } from 'react';
// The Child Component
const StatusSelector = ({ onStatusChange }) => {
const handleChange = (event) => {
// Calling the parent's function with the new value
onStatusChange(event.target.value);
};
return (
<div style={{ margin: '20px 0' }}>
<label htmlFor="filing-status">Select Filing Status: </label>
<select id="filing-status" onChange={handleChange}>
<option value="">--Please choose--</option>
<option value="Single">Single</option>
<option value="Married Filing Jointly">Married Filing Jointly</option>
<option value="Head of Household">Head of Household</option>
</select>
</div>
);
};
// The Parent Component
const TaxCalculator = () => {
const [status, setStatus] = useState('');
const handleSelection = (selectedStatus) => {
console.log("Parent received status:", selectedStatus);
setStatus(selectedStatus);
};
return (
<div style={{ padding: '40px', fontFamily: 'Arial' }}>
<h1>2024 US Tax Estimator</h1>
<p>Please select your IRS filing status to begin.</p>
{/* Passing the callback function to the child */}
<StatusSelector onStatusChange={handleSelection} />
{status && (
<div style={{ marginTop: '20px', fontWeight: 'bold' }}>
Your selected status is: {status}
</div>
)}
</div>
);
};
export default TaxCalculator;You can refer to the screenshot below to see the output.

I have used this pattern thousands of times for forms and interactive dashboards. The key is that the child doesn’t “own” the state; it just notifies the parent of a change.
Manage Complex Data with Lifting State Up
Sometimes you have two sibling components that need to talk to each other.
In React, you cannot send data directly between siblings. You must “lift the state up” to its closest common parent.
I have seen many developers get confused here, but it’s simpler than it sounds.
Example: New York Stock Exchange (NYSE) Tracker
Let’s build a small app where one component allows you to enter a stock ticker, and another displays the current price.
import React, { useState } from 'react';
// Sibling 1: The Input
const StockInput = ({ setTicker }) => {
const [inputValue, setInputValue] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
setTicker(inputValue.toUpperCase());
};
return (
<form onSubmit={handleSubmit} style={{ marginBottom: '20px' }}>
<input
type="text"
placeholder="Enter Ticker (e.g. AAPL)"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button type="submit">Track Stock</button>
</form>
);
};
// Sibling 2: The Display
const StockDisplay = ({ ticker }) => {
// Mock data for the example
const stockPrices = {
'AAPL': 185.92,
'MSFT': 402.56,
'TSLA': 175.05,
'GOOGL': 142.12
};
const price = stockPrices[ticker];
return (
<div style={{ padding: '15px', background: '#f4f4f4', borderRadius: '5px' }}>
{ticker ? (
<p>Current price for <strong>{ticker}</strong>: {price ? `$${price}` : 'Data not found'}</p>
) : (
<p>Please enter a ticker symbol to see the price.</p>
)}
</div>
);
};
// Common Parent: The NYSE Dashboard
const NYSEDashboard = () => {
const [activeTicker, setActiveTicker] = useState('');
return (
<div style={{ padding: '40px' }}>
<h1>Wall Street Market Monitor</h1>
<StockInput setTicker={setActiveTicker} />
<StockDisplay ticker={activeTicker} />
</div>
);
};
export default NYSEDashboard;You can refer to the screenshot below to see the output.

By keeping the activeTicker state in the NYSEDashboard, both children can stay in sync. The StockInput updates the state, and the StockDisplay reads from it.
Best Practices for Component Communication
After years of debugging React apps, I have developed a few rules of thumb.
First, always keep your components as small as possible. If a component is doing too many things, it becomes hard to pass props.
Second, avoid “Prop Drilling.” This happens when you pass props through several layers of components that don’t actually need the data.
If you find yourself passing a prop through more than three levels, it might be time to look at the Context API or a state management library.
Third, use descriptive names for your callback props. Instead of func={handle}, use onUserLogin={handleLogin}.
Use the Context API for Deep Nesting
When your app grows, passing props down a long chain of components becomes tedious.
In these cases, I prefer using the React Context API. It acts like a “global” variable for a specific tree of components.
Example: Theme Toggler for a US News Portal
Let’s say we want to change the theme from Light to Dark across an entire news site.
import React, { createContext, useContext, useState } from 'react';
// 1. Create the Context
const ThemeContext = createContext();
// Header Component (Nested Deeply)
const Header = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<header style={{
background: theme === 'light' ? '#eee' : '#333',
color: theme === 'light' ? '#000' : '#fff',
padding: '10px'
}}>
<h2>USA Today News</h2>
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
</button>
</header>
);
};
// Content Component
const NewsContent = () => {
const { theme } = useContext(ThemeContext);
return (
<div style={{
height: '200px',
background: theme === 'light' ? '#fff' : '#222',
color: theme === 'light' ? '#000' : '#ccc'
}}>
<p>Top Story: Economic trends in the Midwest for 2024.</p>
</div>
);
};
// Parent App Component
const NewsPortal = () => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<div style={{ border: '2px solid black' }}>
<Header />
<NewsContent />
</div>
</ThemeContext.Provider>
);
};
export default NewsPortal;Context is powerful, but don’t over-use it. Use it for data that is truly global, like user authentication or themes.
For most day-to-day tasks, simple props and callbacks are much easier to track.
I hope this guide helps you understand how components talk to each other in React.
In my experience, once you master these patterns, building even the largest applications becomes a simple task.
You may also read:
- Prop Distribution in React Functional Components
- React Google Calendar Component
- How to Return a Component from a React Hook
- Implement Scroll to Component in React

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.