Render Props
Render Props
The term “render prop” refers to a technique in React for sharing code between React components using a prop whose value is a function.
Like Higher-Order Components (HOCs), the Render Props pattern was highly popular before React Hooks were introduced, but it remains a very powerful and flexible pattern in modern React.
The Problem
Imagine you have a component that tracks the mouse position.
function MouseTracker() {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleMouseMove = (e) => setPosition({ x: e.clientX, y: e.clientY });
return (
<div style={{ height: '100vh' }} onMouseMove={handleMouseMove}>
<h1>The mouse position is ({position.x}, {position.y})</h1>
</div>
);
}
What if you want to use that exact same mouse-tracking logic to render a picture of a cat that follows the cursor? You can’t just reuse MouseTracker because its UI is hardcoded to be an <h1>.
The Render Prop Solution
Instead of hardcoding what a component renders, you pass it a function as a prop (often called render or just children). The component calls this function, passing its internal state to it, and the function returns the JSX to render.
function Mouse({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleMouseMove = (e) => setPosition({ x: e.clientX, y: e.clientY });
return (
<div style={{ height: '100vh' }} onMouseMove={handleMouseMove}>
{/* Instead of hardcoding UI, we call the render prop! */}
{render(position)}
</div>
);
}
Now, the Mouse component only handles the logic of tracking the mouse. The parent component decides what the UI looks like.
function App() {
return (
<div>
{/* Usage 1: Render text */}
<Mouse render={(pos) => (
<h1>Mouse is at ({pos.x}, {pos.y})</h1>
)} />
{/* Usage 2: Render a cat image */}
<Mouse render={(pos) => (
<img
src="/cat.png"
style={{ position: 'absolute', left: pos.x, top: pos.y }}
/>
)} />
</div>
);
}
Using children as a Render Prop
You don’t have to name the prop render. It is very common to use the built-in children prop for this pattern. This makes the JSX syntax look slightly cleaner.
function Mouse({ children }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
// ... event logic ...
return <div onMouseMove={handleMouseMove}>{children(position)}</div>;
}
// Usage:
function App() {
return (
<Mouse>
{/* The child of Mouse is literally a function! */}
{(pos) => <h1>Mouse is at ({pos.x}, {pos.y})</h1>}
</Mouse>
);
}
Render Props vs Custom Hooks
In modern React, most logic-sharing problems solved by Render Props are better solved with Custom Hooks (const pos = useMousePosition()). Hooks avoid “wrapper hell” (deeply nested JSX).
However, Render Props are still highly relevant for UI abstractions. For example, a VirtualList component might use a render prop to let you define how a single row looks, while the list handles the complex scrolling logic.
Interview Questions
Q: What is the Render Props pattern?
A: It involves passing a function to a component via a prop (usually named render or leveraging the children prop) which the component calls to know what to render. It was the primary way to share stateful logic (like mouse tracking or window resizing) across components before Hooks existed.