
ReactJS
Different parts of your app often need to work with the same data. Use lifting state and callbacks to keep components in sync.
When multiple components need the same state, move it to their common parent. The parent manages state and passes it down as props.
Moving state "up" the component tree lets you share it. The parent becomes the source of truth, and all components stay in sync.
import { useState } from 'react';
function Parent() {
// State lives here, shared by both children
const [selectedItem, setSelectedItem] = useState(null);
return (
<div>
<List
items={['Apple', 'Banana', 'Cherry']}
onSelect={setSelectedItem}
/>
<Details item={selectedItem} />
</div>
);
}
function List(props) {
return (
<ul>
{props.items.map((item) => (
<li key={item} onClick={() => props.onSelect(item)}>
{item}
</li>
))}
</ul>
);
}
function Details(props) {
return <p>Selected: {props.item}</p>;
}<details>
<summary>📚 More Examples</summary>
// Example: Form data shared with preview
function FormWithPreview() {
const [formData, setFormData] = useState({
title: '',
description: '',
});
const updateField = (field, value) => {
setFormData({ ...formData, [field]: value });
};
return (
<div>
<FormEditor
data={formData}
onUpdate={updateField}
/>
<Preview data={formData} />
</div>
);
}
function FormEditor(props) {
return (
<div>
<input
value={props.data.title}
onChange={(e) => props.onUpdate('title', e.target.value)}
placeholder="Title"
/>
<textarea
value={props.data.description}
onChange={(e) => props.onUpdate('description', e.target.value)}
placeholder="Description"
/>
</div>
);
}
function Preview(props) {
return (
<div>
<h2>{props.data.title}</h2>
<p>{props.data.description}</p>
</div>
);
}</details>
The parent component acts as the mediator between children. It holds state and provides callbacks for children to update it.
import { useState } from 'react';
function ParentMediator() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount(count + 1);
};
const handleDecrement = () => {
setCount(count - 1);
};
return (
<div>
<Display value={count} />
<Controls
onIncrement={handleIncrement}
onDecrement={handleDecrement}
/>
</div>
);
}
function Display(props) {
return <p>Count: {props.value}</p>;
}
function Controls(props) {
return (
<div>
<button onClick={props.onIncrement}>+</button>
<button onClick={props.onDecrement}>-</button>
</div>
);
}<details>
<summary>📚 More Examples</summary>
// Example: Multiple related components
function ShoppingCart() {
const [items, setItems] = useState([]);
const addItem = (product) => {
setItems([...items, product]);
};
const removeItem = (index) => {
setItems(items.filter((item, i) => i !== index));
};
return (
<div>
<ProductCatalog onAddItem={addItem} />
<CartSummary items={items} onRemove={removeItem} />
</div>
);
}
function ProductCatalog(props) {
const products = ['Shirt', 'Pants', 'Shoes'];
return (
<div>
{products.map((p) => (
<button key={p} onClick={() => props.onAddItem(p)}>
Add {p}
</button>
))}
</div>
);
}
function CartSummary(props) {
return (
<ul>
{props.items.map((item, i) => (
<li key={i}>
{item}
<button onClick={() => props.onRemove(i)}>Remove</button>
</li>
))}
</ul>
);
}</details>
Design your component hierarchy with state ownership in mind. Place state as high as needed but no higher.
import { useState } from 'react';
// Too high: Managing detail state at root level
function BadApp() {
const [selectedUser, setSelectedUser] = useState(null);
const [selectedPost, setSelectedPost] = useState(null);
const [isDarkMode, setIsDarkMode] = useState(false);
return <UserDetail user={selectedUser} post={selectedPost} />;
}
// Better: State lives close to where it's used
function GoodApp() {
const [isDarkMode, setIsDarkMode] = useState(false);
return (
<div style={{ background: isDarkMode ? '#000' : '#fff' }}>
<UserSection />
<button onClick={() => setIsDarkMode(!isDarkMode)}>
Toggle Dark Mode
</button>
</div>
);
}
function UserSection() {
const [selectedUser, setSelectedUser] = useState(null);
// Only components that need this state are here
return <div>{selectedUser?.name}</div>;
}| Scenario | Solution |
|---|---|
| One component uses state | Keep it in that component |
| Two children need state | Lift to parent |
| Multiple children need state | Lift to common ancestor |
| Many components need state | Consider Context API |
Ready to practice? Challenges | Next: Interactive Components
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward