Function Children Pattern: Pass a Function via Children
Share data from a parent and let consumers decide how to render it.
Some components own data but shouldn’t dictate the markup. I ran into this with a user object: I wanted to expose it and still leave the rendering flexible, colocated with the consumer.
Who owns the markup?
The straightforward version renders the fields right where the data lives:
function App() {
const user = { name: "John Doe", email: "john@example.com", role: "Developer" };
return (
<div>
<h1>Function Children Pattern</h1>
<h2>{user.name}</h2>
<p>{user.email}</p>
<p>{user.role}</p>
</div>
);
}
export default App;
That couples presentation to the provider. The parent now owns the data and the layout, so any consumer wanting different markup needs the provider to change.
The provider calls children(user)
Instead, a DataProvider keeps the user and calls its children as a function:
function DataProvider({ children }) {
const user = { name: "John Doe", email: "john@example.com", role: "Developer" };
return children(user);
}
function App() {
return (
<div>
<h1>Function Children Pattern</h1>
<DataProvider>
{(user) => (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
<p>{user.role}</p>
</div>
)}
</DataProvider>
</div>
);
}
export default App;
The provider calls, the consumer renders. Data decisions stay in the provider; layout decisions stay with the consumer. This is my default when the data shape is fixed but the UI around it needs flexibility.
One thing to do on the side: document the function signature, which values the parent passes, because nothing at the call site makes that obvious. If the function body grows complicated, move it to a named prop instead. That’s the render props pattern.