What Is the Render Props Pattern in React?
Learn the render props pattern in React — sharing stateful logic via a function prop while the consumer controls rendering.
Expected Interview Answer
The render props pattern is a technique where a component accepts a function as a prop — often literally named `render`, or passed as `children` — and calls that function with internal state or behavior, letting the consumer decide exactly what to render without the component itself dictating the output.
Instead of a component hardcoding its JSX output, it exposes its internal state (like mouse position, form values, or a data-fetch result) by invoking a function prop and passing that state as arguments: `render(internalState)`. The parent then supplies whatever UI it wants, reusing the stateful logic while fully controlling presentation. This solves the same cross-cutting-logic-reuse problem as higher-order components, but avoids some of their pitfalls, like prop-name collisions between multiple wrappers or unclear component hierarchies in DevTools, because everything stays visible in a single component tree with an explicit function call. The main tradeoff is that deeply nested render props can create a visually nested, sometimes hard-to-read JSX structure, informally called “wrapper hell,” which is one reason custom hooks have become the preferred approach for pure logic-sharing since hooks let you avoid the extra component layer altogether while keeping the same flexibility.
- Consumer fully controls rendering while reusing shared stateful logic
- Avoids prop-name collisions common with stacked higher-order components
- Keeps everything in one visible component tree, easier to trace in DevTools
- Composes well for utilities like mouse-tracking, data-fetching, or list virtualization
AI Mentor Explanation
The render props pattern is like a scoring official who tracks every ball bowled internally but, instead of publishing a fixed scoreboard layout, hands the raw ball-by-ball data to whoever is broadcasting and lets each broadcaster decide their own on-screen graphics. One channel might show a simple run tally, another a detailed wagon-wheel chart, both fed by the exact same internal tracking function. The official never dictates the visual output, only supplies the data through a callback each time a ball is bowled. That data-in-callback, presentation-left-to-the-caller design is exactly the render props pattern.
Step-by-Step Explanation
Step 1
Component manages internal state
The reusable component tracks state internally, e.g. mouse position via a listener.
Step 2
State passed via a function prop
Instead of rendering fixed JSX, it calls this.props.render(state) or renders props.children(state).
Step 3
Consumer supplies the rendering function
The parent passes a function that receives the state and returns whatever JSX it wants.
Step 4
Component invokes it on every relevant update
Each time internal state changes, the render function is called again with fresh values.
What Interviewer Expects
- Clear explanation of a function prop receiving internal state to produce output
- Comparison with higher-order components and their prop-collision tradeoffs
- Awareness of the “wrapper hell” readability tradeoff with deep nesting
- Mention of custom hooks as the modern alternative for the same use cases
Common Mistakes
- Confusing render props with simply passing JSX as a children prop without a function
- Not memoizing the render function, causing unnecessary re-renders on every parent render
- Deeply nesting multiple render-prop components, hurting readability
- Reaching for render props when a simpler custom hook solves the same problem more cleanly
Best Answer (HR Friendly)
“Render props is a pattern where a component that tracks some data — like the mouse position — does not decide how to show it. Instead, it hands that data to a function you provide, and your function decides exactly what to render with it. It is a flexible way to reuse behavior while keeping full control over the visuals.”
Code Example
function MouseTracker({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 })
useEffect(() => {
const handleMove = (e) => setPosition({ x: e.clientX, y: e.clientY })
window.addEventListener('mousemove', handleMove)
return () => window.removeEventListener('mousemove', handleMove)
}, [])
return render(position)
}
// Usage:
// <MouseTracker render={({ x, y }) => <p>Mouse at {x}, {y}</p>} />Follow-up Questions
- How would you rewrite this MouseTracker as a custom hook instead?
- What performance issue can arise from passing an inline render function on every render?
- How does render props avoid the prop-collision problem of stacked HOCs?
- What is “wrapper hell” and how does it relate to nested render props?
MCQ Practice
1. In the render props pattern, how does a component share its internal state?
The component invokes a supplied function (often named render or children) with its internal state.
2. What common issue can arise from deeply nested render props components?
Stacking multiple render-prop components visually nests the JSX, hurting readability.
3. What modern alternative often replaces render props for pure logic reuse?
Custom hooks provide the same shared-logic benefit without adding an extra component layer.
Flash Cards
What is a render prop? — A function prop a component calls with its internal state to let the consumer decide what to render.
What problem does render props share with HOCs? — Reusing cross-cutting stateful logic across components.
What readability downside can render props cause? — "Wrapper hell" — deeply nested JSX when stacking several render-prop components.
What commonly replaces render props today? — Custom hooks, which avoid the extra component layer entirely.