Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
State sharing is the process of making the same data available to multiple components that need it. In React, the most common pattern for sharing state is "lifting state up" - moving state to the closest common ancestor component.
Components have separate state that can't synchronize.
State lives in parent, passed down to children.
Lifting state up means moving state from child components to their closest common parent. The parent becomes the "source of truth" and passes the state down as props.
Find data that multiple components need to access or modify
Remove state from children, add it to their closest ancestor
Send state as props and update functions as callbacks
Multiple counters sharing the same state through lifting state up
import React from 'react';
import { createRoot } from 'react-dom/client';
function App() {
const [count, setCount] = React.useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
const reset = () => setCount(0);
return (
<div className="app">
<h1>🔄 Synchronized Counters</h1>
<p className="description">
All counters share the same state from the parent component
</p>
<div className="controls">
<button onClick={decrement} className="btn btn-danger">
➖ Decrease
</button>
<button onClick={reset} className="btn btn-secondary">
🔄 Reset
</button>
<button onClick={increment} className="btn btn-primary">
➕ Increase
</button>
</div>
<div className="counters-grid">
<CounterDisplay
label="Counter A"
count={count}
color="blue"
/>
<CounterDisplay
label="Counter B"
count={count}
color="green"
/>
<CounterDisplay
label="Counter C"
count={count}
color="purple"
/>
</div>
<div className="state-info">
<h3>🔍 State Location</h3>
<p>
<strong>Parent Component:</strong> Holds the count state
</p>
<p>
<strong>Child Components:</strong> Receive count as props
</p>
<p>
<strong>Update Flow:</strong> Child → Parent → All Children
</p>
</div>
</div>
);
}
function CounterDisplay({ label, count, color }) {
return (
<div className={'counter-display counter-' + color}>
<h3>{label}</h3>
<div className="count-value">{count}</div>
<p className="count-label">Current Value</p>
</div>
);
}
const root = createRoot(document.getElementById('root'));
root.render(React.createElement(App));Loading preview...
Multiple components sharing and manipulating the same todo data
import React from 'react';
import { createRoot } from 'react-dom/client';
function TodoApp() {
const [todos, setTodos] = React.useState([
{ id: 1, text: 'Learn React state sharing', completed: false },
{ id: 2, text: 'Build a todo app', completed: true },
{ id: 3, text: 'Master lifting state up', completed: false }
]);
const [filter, setFilter] = React.useState('all');
const addTodo = (text) => {
const newTodo = {
id: Date.now(),
text: text.trim(),
completed: false
};
setTodos([...todos, newTodo]);
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
const clearCompleted = () => {
setTodos(todos.filter(todo => !todo.completed));
};
// Derived state - calculated from todos
const filteredTodos = todos.filter(todo => {
if (filter === 'active') return !todo.completed;
if (filter === 'completed') return todo.completed;
return true;
});
const stats = {
total: todos.length,
active: todos.filter(todo => !todo.completed).length,
completed: todos.filter(todo => todo.completed).length
};
return (
<div className="todo-app">
<h1>📝 Shared Todo List</h1>
<p className="subtitle">
All components share the same todos array from the parent
</p>
<TodoInput onAdd={addTodo} />
<TodoStats stats={stats} />
<TodoFilter
currentFilter={filter}
onFilterChange={setFilter}
/>
<TodoList
todos={filteredTodos}
onToggle={toggleTodo}
onDelete={deleteTodo}
/>
{stats.completed > 0 && (
<div className="clear-section">
<button
onClick={clearCompleted}
className="clear-btn"
>
🧹 Clear {stats.completed} completed
</button>
</div>
)}
<div className="state-flow">
<h3>🔄 State Flow Diagram</h3>
<div className="flow-diagram">
<div className="flow-box parent">TodoApp (State Owner)</div>
<div className="flow-arrows">
<span>↓ props ↓</span>
</div>
<div className="flow-children">
<div className="flow-box child">TodoInput</div>
<div className="flow-box child">TodoStats</div>
<div className="flow-box child">TodoFilter</div>
<div className="flow-box child">TodoList</div>
</div>
</div>
</div>
</div>
);
}
function TodoInput({ onAdd }) {
const [input, setInput] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (input.trim()) {
onAdd(input);
setInput('');
}
};
return (
<form onSubmit={handleSubmit} className="todo-input">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="What needs to be done?"
className="input-field"
/>
<button type="submit" className="add-btn">
➕ Add
</button>
</form>
);
}
function TodoStats({ stats }) {
return (
<div className="todo-stats">
<div className="stat-item">
<span className="stat-number">{stats.total}</span>
<span className="stat-label">Total</span>
</div>
<div className="stat-item">
<span className="stat-number">{stats.active}</span>
<span className="stat-label">Active</span>
</div>
<div className="stat-item">
<span className="stat-number">{stats.completed}</span>
<span className="stat-label">Done</span>
</div>
</div>
);
}
function TodoFilter({ currentFilter, onFilterChange }) {
return (
<div className="todo-filter">
{['all', 'active', 'completed'].map(filter => (
<button
key={filter}
onClick={() => onFilterChange(filter)}
className={'filter-btn ' + (currentFilter === filter ? 'active' : '')}
>
{filter.charAt(0).toUpperCase() + filter.slice(1)}
</button>
))}
</div>
);
}
function TodoList({ todos, onToggle, onDelete }) {
if (todos.length === 0) {
return (
<div className="empty-state">
<p>🎉 No todos to show!</p>
</div>
);
}
return (
<div className="todo-list">
{todos.map(todo => (
<div key={todo.id} className={'todo-item ' + (todo.completed ? 'completed' : '')}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onToggle(todo.id)}
className="todo-checkbox"
/>
<span className="todo-text">{todo.text}</span>
<button
onClick={() => onDelete(todo.id)}
className="delete-btn"
>
🗑️
</button>
</div>
))}
</div>
);
}
const root = createRoot(document.getElementById('root'));
root.render(React.createElement(TodoApp));Loading preview...
State sharing through lifting state up is React's fundamental pattern for component communication. Master this concept before moving to advanced solutions like Context API or state management libraries.