The Prop Drilling Problem
Overview
As your React app grows, the component tree becomes deep. If you have a piece of state at the very top (like `currentUser`) and a component at the very bottom needs it (like an `Avatar` in the Header), you have to pass that state down through every single intermediate component as a prop. Those intermediate components don't even care about the data; they are just acting as a bucket brigade. This nightmare is called 'Prop Drilling', and it makes code incredibly brittle and hard to refactor.
Syntax
If we suddenly decide the `Navigation` needs the `logout` function too, we have to modify the props of App, Layout, Header, AND Navigation. This is highly inefficient developer experience.
// App holds the state
function App() {
const [user, setUser] = useState({ name: 'Alice' });
return <Layout user={user} />;
}
// Layout doesn't need 'user', but has to pass it down
function Layout({ user }) {
return <Header user={user} />;
}
// Header doesn't need 'user', but has to pass it down
function Header({ user }) {
return <Navigation user={user} />;
}
// Navigation finally uses it!
function Navigation({ user }) {
return <span>Welcome, {user.name}</span>;
}Common Pitfalls
- Reaching for a Global State manager (like Redux) immediately. Before using global state, see if you can solve the problem using 'Component Composition' (passing components as `children`).
Interview Tips
- When asked 'What problem does Redux/Context solve?', 'Prop Drilling' should be the very first words out of your mouth. It's the primary motivation for Global State.
Real-World Example
Visualizing the Component Tree. Think of a massive eCommerce site where the 'Cart Count' state lives in `App`, but the actual `CartIcon` is buried inside `App -> Header -> TopBar -> Icons -> CartIcon`.
// App.jsx
function App() {
const [cartCount, setCartCount] = useState(0);
return <Header cartCount={cartCount} />;
}
// Header.jsx
function Header({ cartCount }) {
return <TopBar cartCount={cartCount} />;
}
// TopBar.jsx
function TopBar({ cartCount }) {
return <Icons cartCount={cartCount} />;
}
// Icons.jsx
function Icons({ cartCount }) {
return <CartIcon count={cartCount} />;
}