How to lift state up in React
Lifting state up in React involves moving shared state from child components to their nearest common ancestor, enabling proper data flow and communication between sibling components. As the creator of CoreUI, a widely used open-source UI library, I’ve implemented state lifting patterns in thousands of React applications for dashboard filters, form management, and component synchronization. From my expertise, the most effective approach is identifying shared state needs and moving state to the closest common parent with callback props for updates. This method provides centralized state management and clear data flow throughout the component hierarchy.
Move shared state to the nearest common ancestor and pass data down with callback functions for updates.
import { useState } from 'react'
function App() {
const [selectedUser, setSelectedUser] = useState(null)
const [users, setUsers] = useState([
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' }
])
const handleUserSelect = (user) => {
setSelectedUser(user)
}
const handleUserUpdate = (updatedUser) => {
setUsers(prevUsers =>
prevUsers.map(user =>
user.id === updatedUser.id ? updatedUser : user
)
)
setSelectedUser(updatedUser)
}
return (
<div>
<UserList
users={users}
selectedUser={selectedUser}
onUserSelect={handleUserSelect}
/>
<UserDetails
user={selectedUser}
onUserUpdate={handleUserUpdate}
/>
</div>
)
}
function UserList({ users, selectedUser, onUserSelect }) {
return (
<div>
{users.map(user => (
<div
key={user.id}
onClick={() => onUserSelect(user)}
style={{
background: selectedUser?.id === user.id ? '#f0f0f0' : 'white'
}}
>
{user.name}
</div>
))}
</div>
)
}
function UserDetails({ user, onUserUpdate }) {
if (!user) return <div>Select a user</div>
return (
<div>
<h3>{user.name}</h3>
<p>{user.email}</p>
<button onClick={() => onUserUpdate({ ...user, name: user.name + ' (Updated)' })}>
Update User
</button>
</div>
)
}
State is lifted to the App component where both UserList and UserDetails can access shared data. The parent manages state through useState and passes data down as props while providing callback functions for child components to trigger state updates. This ensures single source of truth and predictable data flow.
Best Practice Note:
This is the same state lifting pattern we use in CoreUI React components for managing shared state across dashboard widgets and form sections.