Back to all notes

Function Children Pattern: Pass a Function via Children

Share data from a parent and let consumers decide how to render it.

2 min read

Introduction

The function children pattern passes a function as children so a parent can provide data and the consumer decides how to render it. It’s a powerful way to keep data and layout concerns separate.

Why this matters

Sometimes a parent owns data but doesn’t want to dictate the markup. By passing a function as children, the parent can provide values and the consumer decides how to render them.

The problem

We want to expose a user object while keeping the rendering flexible and colocated with the consumer.

Inefficient approach

Hard‑coding layout around data couples presentation to the provider:

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;

The solution

Create a DataProvider that 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;

Step-by-step

  1. Create DataProvider that owns the user data.
  2. Accept children as a function and call it with user.
  3. In the consumer, render UI inside the function with the provided user.
  4. Keep layout decisions in the consumer; keep data in the provider.
  5. Prefer this when the data shape is fixed but UI needs flexibility.

Tips

  • Document the function signature (which values the parent passes).
  • Prefer function children when a component controls data and the consumer controls layout.
  • If the function grows complex, consider moving it to a named prop (render props).

Knowledge base

Problem snippet:

<h2>{user.name}</h2>

Solution snippet:

<DataProvider>
  {(user) => <h2>{user.name}</h2>}
</DataProvider>