Render Props

Understand the Render Props pattern — a technique for sharing logic by passing a render function as a prop. Learn when it is still useful and how it relates to hooks and compound components.

Last reviewed: January 2025

·React 16+React 18React 19
✅
Quick Understanding: Render Props is a pattern where a component receives a function as a prop and calls it to determine what to render. The function receives data from the component and returns JSX. It was the primary pattern for sharing stateful logic before hooks. Today, custom hooks replace most render prop use cases, but the pattern still appears in library APIs.

🔍 What Is It?

A render prop is a prop that is a function returning JSX:

// Component with a render prop
<DataProvider
  url="/api/claims"
  render={(data, loading) => (
    loading ? <Spinner /> : <ClaimsList claims={data} />
  )}
/>

The children prop as a function is the most common form:

<Toggle>
  {({ isOn, toggle }) => (
    <button onClick={toggle}>{isOn ? 'On' : 'Off'}</button>
  )}
</Toggle>

The component owns the state/logic; the caller controls the rendering.

🎯 Why Do We Need It?

Before hooks, render props were the cleanest way to share stateful logic without HOC wrapper hell. The component encapsulates the logic (data fetching, toggle state, mouse position) and exposes it to the caller via a function prop.

In 2024, custom hooks replace render props for most use cases. But render props still appear in:

  • →Library APIs (react-table, Downshift, React Final Form)
  • →Cases where the consuming component needs to control rendering based on dynamic data
  • →Slot patterns in design systems

🏗️ What Happens in Real Projects?

Render props you will encounter:

  • →React Router v5's <Route render={(props) => <Component {...props} />} />
  • →react-table's cell render functions
  • →Downshift's children function for accessible dropdowns
  • →Custom <DataTable renderRow={(row) => <CustomRow data={row} />} />
  • →<Formik render={(formProps) => <MyForm {...formProps} />} />

⚙️ How It Works

The component with the render prop:

  1. Manages its own state and logic
  2. Calls the render prop function (or children function) with its state
  3. Renders the JSX returned by the function

The caller:

  1. Passes a function that receives the state
  2. Returns JSX based on that state
  3. Has full control over rendering without managing the logic

💻 Example

Render Props Patterns — Classic render prop and children-as-function patterns.

tsx
interface DataTableProps<T> {
  data: T[];
  columns: Column<T>[];
  renderRow: (item: T, index: number) => React.ReactNode;
  renderEmpty?: () => React.ReactNode;
  loading?: boolean;
}

function DataTable<T extends { id: string }>({
  data,
  columns,
  renderRow,
  renderEmpty,
  loading,
}: DataTableProps<T>) {
  if (loading) return <TableSkeleton columns={columns.length} />;
  if (data.length === 0) return renderEmpty ? renderEmpty() : <EmptyState />;

  return (
    <table>
      <thead>
        <tr>{columns.map(col => <th key={col.key}>{col.label}</th>)}</tr>
      </thead>
      <tbody>
        {data.map((item, i) => (
          <tr key={item.id}>{renderRow(item, i)}</tr>
        ))}
      </tbody>
    </table>
  );
}

// Usage — caller controls row rendering
<DataTable
  data={claims}
  columns={CLAIM_COLUMNS}
  renderRow={(claim) => (
    <>
      <td>{claim.policyNumber}</td>
      <td>{claim.holderName}</td>
      <td><StatusBadge status={claim.status} /></td>
      <td><ActionMenu claimId={claim.id} /></td>
    </>
  )}
  renderEmpty={() => <EmptyState message="No claims match your filters" />}
/>

🤔 Common Confusions

❓ Should I use render props or custom hooks in 2024?

For logic sharing: custom hooks. They are simpler, do not add JSX nesting, and compose more cleanly. For rendering flexibility (like DataTable's renderRow): render props are still the right tool. The distinction: use hooks for logic, use render props for rendering control.

🚨 Common Production Issues

**Performance: Inline render prop functions** — Passing an inline arrow function as a render prop creates a new function on every parent render, causing unnecessary re-renders of the child. Extract to a named function or use useCallback.

✅ Best Practices

Prefer custom hooks for logic reuse — render props for rendering control

Use children as a function for the most natural API

Avoid deeply nested render props — extract to custom hooks instead

Use useCallback for render prop functions passed to memoised components

🏛️ Architect's Note

Senior Architect's Perspective

Render props are a pattern from pre-hooks React that solved real problems elegantly. Today, custom hooks solve the same problems with less ceremony. The render prop pattern lives on in library APIs (react-table, Downshift) and in cases where the consumer genuinely needs to control rendering. When you see a render prop in a library API, understand it as "the library owns the logic, you own the rendering" — that mental model is still valid and useful.

💬 Frequently Asked Questions

What is children as a function?

Instead of a named render prop, the children prop itself is a function: <Toggle>{({ isOn }) => <button>{isOn ? "On" : "Off"}</button>}</Toggle>. This is the most common render prop form because it reads naturally. The component calls this.props.children(state) or props.children(state) to get the JSX.

🎯 Key Takeaways

1Render props share logic by passing a render function as a prop
2Custom hooks have replaced render props for logic sharing in modern React
3Render props are still useful for rendering control (DataTable renderRow)
4Children as a function is the most common render prop form
5Use useCallback for render prop functions to prevent unnecessary re-renders

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these React references to verify the concept in official docs and continue into the most relevant SplashRide pages.

Related SplashRide pages

SplashRide React learning path

Browse the full React topic collection and learning order on SplashRide.

React Interview Prep

Practice React interview questions and scenario-based answers.

Frontend Engineer Career Path

A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.

Python Developer Career Path

A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.

Custom Hooks

Master custom hooks — the most powerful pattern in React for sharing stateful logic between components. Learn how to extract, compose, and test custom hooks the way senior engineers do in enterprise applications.

Higher Order Components

Understand Higher Order Components (HOCs) — a React pattern for reusing component logic. Learn when they are still useful, when custom hooks are better, and how senior engineers use them in 2024.