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.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
What is the difference between typeof and instanceof in JavaScript
What is the difference between typeof and instanceof in JavaScript

How to change opacity on hover in CSS
How to change opacity on hover in CSS

How to disable a button in JavaScript
How to disable a button in JavaScript

How to round a number to two decimal places in JavaScript
How to round a number to two decimal places in JavaScript

Answers by CoreUI Core Team