In React, what is the render-prop pattern — including the function-as-children form — and how does the callback get the data it renders?
answer
- a prop that is a function
- caller writes the markup
- children is just a prop too
- owner calls it with its state
- the callback is not a component
basics
~20 sA render prop is a prop whose value is a function that returns JSX. The component holding the state calls that function during its own render and passes its data in as arguments, so the caller controls the markup while the component keeps the behaviour.
solid answer
~50 sA render prop is a prop whose value is a function returning renderable output. The component that owns the state calls that function while it renders, passing its data as arguments, so the caller supplies the markup and the component keeps the logic. The name `render` is only a convention — because `children` is an ordinary prop, the same idea written as `<MouseTracker>{({ x, y }) => <Dot x={x} y={y} />}</MouseTracker>` is the function-as-children form. The callback is not a component: it has no state of its own, you must not call hooks inside it, and the elements it returns become part of the owning component's subtree. Before hooks this was one of the two main ways to share stateful logic; in React 19 a custom hook is the default, and render props survive mostly in libraries that must own rendering, such as virtualized lists.
go deeper
Be able to spot the shape when you read code — a function sitting where JSX usually goes — and say plainly that the component calls that function and passes its own data in.
Explain that children is an ordinary prop, which is why a function can be written between the tags, and that the callback executes inside the owner's render rather than as a component of its own.
Show the judgment call: for logic that renders nothing, a custom hook is the better default now, and you should be able to say what a render prop still buys you when the reusable unit owns the markup.
Frame it as API design for a library boundary — a render prop hands consumers control of the markup at the cost of a callback they must keep cheap, and that contract is hard to change once published.
## The problem the pattern solves A React component does two things at once: it holds behaviour (state, subscriptions, event wiring) and it produces markup. That is convenient until two screens want the same behaviour with different markup. Copying the component and editing its JSX duplicates the logic; making the markup configurable with a pile of boolean props produces a component nobody can read. The render-prop pattern splits the two: one component owns the behaviour, and the markup arrives from outside as a function. ## The mechanics A render prop is nothing more exotic than a prop whose value happens to be a function returning something React can render. The owning component calls it during its own render and passes its state in: ```jsx function MouseTracker({ render }) { const [pos, setPos] = useState({ x: 0, y: 0 }); return ( <div onPointerMove={(e) => setPos({ x: e.clientX, y: e.clientY })}> {render(pos)} </div> ); } <MouseTracker render={({ x, y }) => <p>{x}, {y}</p>} /> ``` Nothing in React treats the name `render` specially. `MouseTracker` could just as well accept `children`, `renderItem`, or `component`. What makes it a render prop is the shape — a function in, elements out — not the identifier. ## Function as children `children` is an ordinary prop; JSX simply assigns whatever sits between the opening and closing tags to it. Usually that is more JSX, but a single expression that evaluates to a function works exactly the same way: ```jsx <MouseTracker> {({ x, y }) => <Cursor x={x} y={y} />} </MouseTracker> ``` and inside, `children(pos)` instead of `render(pos)`. This is the *function as a child* form. It reads better because the callback ends up where a reader expects the component's content to be, and it avoids the awkwardness of a long arrow function jammed into an attribute. There is no behavioural difference — the same mechanism, two spellings. ## Inversion of control The useful property is that the direction of control is inverted. Ordinarily a parent hands data down to a child it chose. Here the *child* component owns the data and hands it back up to a function the parent wrote. That is why one `MouseTracker` can serve a coordinate readout on one page, a drag ghost on another, and a heat-map probe on a third, without ever knowing about any of them. It also means the callback runs in the *caller's* lexical scope. It can close over the caller's props, state and handlers freely, which is why render props were able to replace patterns that otherwise needed explicit context plumbing. ## What React actually sees The callback is invoked during `MouseTracker`'s render, and the elements it returns are placed in `MouseTracker`'s output. Two consequences follow, and both are commonly missed: - The callback is **not a component**. It has no state, no lifecycle, and no entry in the component tree of its own. Calling a hook inside it breaks the Rules of Hooks, because the owner may call it zero times, once, or many times per render. - Because the callback is created fresh on every render of the caller, it is a new function identity each time. That is normally irrelevant, but it does mean the receiving component cannot skip work by comparing the prop to its previous value. ## Where you actually meet it now Since hooks arrived, most logic reuse moved to custom hooks, and the majority of hand-written render props in application code have been replaced. The pattern did not vanish, though — it is still the natural API whenever the reusable unit must *render* something rather than merely compute something. Virtualized lists take an item renderer, because only the list knows which indexes exist; drag-and-drop and measurement wrappers take a function so they can supply live values that only exist inside their own subtree; headless component libraries hand you state plus prop objects and let you write the markup. So the practical interview frame is: recognise the shape instantly when reading code, explain that `children` being a plain prop is what makes the function-as-child form legal, and be able to say why a hook is the better default for logic that renders nothing.
- Why does `render` have no special meaning to React, and what happens if I name the prop something else?React never inspects prop names beyond `key` and `ref`; everything else is handed to your component untouched. A render prop works because your own code calls the value — `props.render(data)`, `props.children(data)`, `props.renderRow(data)`. Renaming it changes only readability, which is why library APIs use descriptive names like `renderItem` or the function-as-children form.
- Can I call a hook inside a render-prop callback?No. The callback runs inside the owning component's render, and the owner decides how often — a list renderer may call it once per row, or not at all when the list is empty. Hooks require the same calls in the same order on every render of a component, so a hook inside the callback would break that ordering. Move the hook into the component itself.
The component is a surveyor who measures the site and hands you the numbers; you decide what the drawing looks like. It never sees your drawing, and you never take the measurements.
saying these in an interview costs you the question
- Thinks the prop must literally be named render
- Believes the callback is its own component with state
- Says function-as-children is a different mechanism from a render prop
- Confuses it with passing a component type as a prop
- Claims you can call hooks inside the callback