Prop drilling is passing the same prop through many intermediate components that do not use it, only to hand it to a component deeper in the tree. It is not always wrong, but it becomes a problem when every layer must know about data it never touches. Component composition and context each offer a cleaner path.
What prop drilling looks like
A signed-in user object starts in App and reaches UserMenu after passing through two intermediate components that never read it.
function App({ currentUser }) {
return <Layout currentUser={currentUser} />;
}
function Layout({ currentUser }) {
return <UserMenu currentUser={currentUser} />;
}
function UserMenu({ currentUser }) {
return <span>{currentUser.name}</span>;
}App holds the data, but Layout only forwards it. Layout must declare a prop it never reads, just to move the value one level down.
When prop drilling is actually fine
Props are explicit, and explicitness is a feature. A little forwarding keeps the data flow visible and makes each component easy to reuse.
- One or two intermediate levels: props are usually the right choice.
- The intermediate components genuinely use the data: props are correct.
- Several layers that only forward: reconsider the structure.
Treat prop drilling as a smell, not a bug. Fix it when the forwarding chain grows or when many siblings need the same value.
Fix with composition
When one deep component needs the data, pass that component as children instead of threading the data through every layer.
function App({ currentUser }) {
return (
<Layout>
<UserMenu currentUser={currentUser} />
</Layout>
);
}
function Layout({ children }) {
return <aside>{children}</aside>;
}Layout no longer knows about currentUser. App places UserMenu directly inside Layout through the children prop, so the data travels one level instead of many.
Fix with context
When several distant components need the same value, context removes the forwarding chain entirely. Create a context, provide it near the top, and read it where it is used.
import { createContext, useContext } from "react";
const UserContext = createContext(null);
function UserMenu() {
const currentUser = useContext(UserContext);
return <span>{currentUser.name}</span>;
}
function App({ currentUser }) {
return <UserContext value={currentUser}><Layout /></UserContext>;
}UserMenu reads currentUser directly from the provider, and Layout does not need to know about it. The tradeoff is that the data flow is now implicit, so a reader is harder to trace than a prop chain.
Choosing the right fix
Match the fix to the shape of the problem. Composition suits a single deep consumer, while context suits values many components share.
| Situation | Fix |
|---|---|
| One deep component needs the data | Composition with children |
| Many distant components need the data | Context |
| Data only moves one or two levels | Keep props |
What to learn next
Context is the stronger tool, so learn the full create, provide, read flow in the React context tutorial. To decide between the two approaches with examples, see context vs props.
Rune AI
Key Insights
- Prop drilling means forwarding a prop through components that do not use it.
- One or two levels of forwarding are usually fine.
- Composition with children removes the middle layers.
- Context removes the chain when many distant components share data.
- Choose the fix based on how many components need the value.
Frequently Asked Questions
Is prop drilling always bad?
What is the fastest fix for prop drilling?
When should I use context instead?
Conclusion
Prop drilling is the act of threading a prop through components that do not use it. It is a sign to reconsider structure, not always a bug. Fix a single deep consumer with composition, and fix widely shared data with context.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.