Prop Drilling

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

Prop Drilling

Prop Drilling is a term used to describe a common, frustrating pattern in React where data is passed down through multiple layers of components that don’t actually need the data themselves, simply to get it to a deeply nested component that does.

The Scenario

Imagine an application with this structure:
<App /> -> <Layout /> -> <Sidebar /> -> <UserProfile /> -> <Avatar />

The <App /> component fetches the user object. The deeply nested <Avatar /> component needs the user.profilePicture URL to display the image.

The Prop Drilling Solution (Bad):
To get the data from <App /> to <Avatar />, you have to pass it as a prop through every single intermediate component.

function App() {
  const user = { name: 'John', image: 'avatar.png' };
  return <Layout user={user} />;
}

// Layout doesn't care about 'user', it just passes it down
function Layout({ user }) {
  return <Sidebar user={user} />;
}

// Sidebar doesn't care about 'user', it just passes it down
function Sidebar({ user }) {
  return <UserProfile user={user} />;
}

// UserProfile finally uses it to render the Avatar
function UserProfile({ user }) {
  return <Avatar image={user.image} />;
}

Why is Prop Drilling bad?

  1. Boilerplate: It requires writing excessive, repetitive code.
  2. Coupling: It couples intermediate components to data they don’t care about. If <Sidebar /> is meant to be a reusable UI layout component, it shouldn’t know anything about a “user” object.
  3. Maintenance: If you rename the prop or change its shape, you have to update every single component in the chain.

How to solve Prop Drilling

There are three primary ways to solve Prop Drilling in React, and interviewers expect you to know when to use each.

1. Component Composition (The best, most overlooked solution)

Instead of passing data down, you pass the components themselves down as children. This allows the parent to render the deeply nested component directly, giving it the data immediately.

function App() {
  const user = { name: 'John', image: 'avatar.png' };
  
  // App renders Avatar directly and passes it into Layout!
  return (
    <Layout>
      <Sidebar>
        <UserProfile>
          <Avatar image={user.image} />
        </UserProfile>
      </Sidebar>
    </Layout>
  );
}

// Layout just renders {children}. It knows nothing about the user.
function Layout({ children }) {
  return <div className="layout">{children}</div>;
}

2. React Context API

If the data is needed by many components scattered across different branches of the tree (e.g., a “Theme” or “Current User”), Component Composition might not be viable. In this case, you use the Context API to “teleport” the data directly to the components that need it, bypassing the intermediate layers.

3. Global State Managers (Redux, Zustand)

If the deeply nested data changes frequently and causes performance issues, or if the logic is incredibly complex, you might move the data out of the React tree entirely into a global state manager like Zustand or Redux.

Interview Questions

Q: What are three distinct ways to solve Prop Drilling?
A:

  1. Use the Context API.
  2. Use Global State Managers (Redux, Zustand).
  3. Use Component Composition (passing the deeply nested child component itself down as a children prop, keeping the state logic at the top).