Pass a Function as Children to Share Logic
Render Props
Render props are a pre-hooks technique for sharing stateful logic — pass a function as `children` and call it with the data.
What you'll learn
- Recognize the render-props pattern
- See why hooks usually replace it
A render prop is when a component’s children is a function.
The component calls that function with some data, and the function
returns JSX.
This was the dominant pattern for sharing stateful logic before hooks. You don’t write it much in new code, but you’ll see it.
The Pattern
function MouseTracker({ children }) {
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
function onMove(e) { setPos({ x: e.clientX, y: e.clientY }); }
window.addEventListener("mousemove", onMove);
return () => window.removeEventListener("mousemove", onMove);
}, []);
return children(pos);
}
// usage
<MouseTracker>
{({ x, y }) => <p>Mouse at {x}, {y}</p>}
</MouseTracker> The “share” is: MouseTracker knows how to track the mouse. The
caller knows what to render with the mouse position.
Why Hooks Won
The same logic as a hook:
function useMousePosition() {
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
function onMove(e) { setPos({ x: e.clientX, y: e.clientY }); }
window.addEventListener("mousemove", onMove);
return () => window.removeEventListener("mousemove", onMove);
}, []);
return pos;
}
// usage
function App() {
const { x, y } = useMousePosition();
return <p>Mouse at {x}, {y}</p>;
} Less JSX nesting, easier to compose, simpler to type. Hooks replaced 90% of render-props use cases.
Where Render Props Still Make Sense
- Libraries that want to wrap their internals — e.g., react-router’s
<Routes>and<Route>compose like this in older versions - Components that need to inject data DURING render — like virtualization libraries that decide which children to render based on size
If you’re writing application code, reach for a custom hook first.
Up Next
Another pre-hooks pattern.
Higher-Order Components →