A Patterns.dev perspective + real‑world examples
“A render prop is a prop whose value is a function that returns JSX.”
The render props pattern lets components share logic by delegating what to render to a function supplied by their parent. This article summarises Lydia Hallie & Addy Osmani’s take in Learning Patterns and shows how to apply it in practice.
1 Why Render Props?
Higher‑Order Components (HOCs) once ruled the reusability roost, but they introduce naming collisions and “invisible” props. Render props solve this by explicitly passing data through a function parameter, avoiding prop clashes and clarifying where data comes from.
TL;DR benefits
Benefit | Why it matters |
---|---|
Explicit data flow | The arguments list shows exactly what’s provided |
No prop name collisions | You choose argument names, not the HOC |
Easy logic/markup separation | State lives in the wrapper, UI lives in the function |
2 A Mini Example
// <Title> renders whatever its caller returns
const Title = ({ render }) => render();
// Usage
<Title render={() => <h1>✨ I am a render prop! ✨</h1>} />
Because Title
delegates its output, you can reuse it with totally different UI every time.
3 Passing Data Down
A render‑prop component usually provides data as an argument:
function Component({ render }) {
const data = { loggedIn: true };
return render(data);
}
<Component render={({ loggedIn }) => <Status ok={loggedIn} />} />
Now the consumer decides how to render based on data
.
4 Temperature Converter Demo
Below is the refactor straight from the book:
function Input(props) {
const [value, setValue] = useState("");
return (
<>
<input value={value} onChange={e => setValue(e.target.value)} />
{props.render(value)}
</>
);
}
export default function App() {
return (
<Input render={value => (
<>
<Kelvin value={value} />
<Fahrenheit value={value} />
</>
)}/>
);
}
Kelvin
and Fahrenheit
gain access to the user’s input without lifting state all the way up the tree.
5 Children‑as‑a‑Function Variant
Instead of a dedicated render
prop, you can pass the function as the child:
<Input>
{value => (
<>
<Kelvin value={value} />
<Fahrenheit value={value} />
</>
)}
</Input>
Under the hood you invoke props.children(value)
. Same pattern, different syntax.
6 5+ Real‑World Use Cases
Library / Component | What the render prop does | Why it’s handy |
---|---|---|
React Router <Route> |
Supplies match , history , location objects so you can decide what to render for a URL. |
Avoids wrapping components with HOCs just for routing context. |
Formik <Formik> |
Gives values , errors , touched , and helpers like setFieldValue . |
Lets you build custom forms without being locked into <Field> markup. |
Downshift <Downshift> |
Provides state & helpers (getInputProps , isOpen , highlightedIndex ) for accessible dropdowns. |
Separates autocomplete logic from UI, so you can render any dropdown design. |
React‑Spring <Spring> / <Transition> |
Passes animated style values into your render function every frame. | You choose the element; the library handles physics & interpolation. |
React‑Motion <Motion> |
Similar to React‑Spring; delivers interpolated styles so you can animate anything. | Keeps animation logic out of component body. |
Apollo Client <Query> / <Mutation> (pre‑hooks) |
Supplies loading , data , error , and functions like mutate . |
Collocates GraphQL data with the UI that needs it—without nesting providers. |
These libraries leveraged render props to expose powerful behaviour through a tiny API surface long before hooks existed.
7 Pros & Cons According to the Book
✅ Pros
- Clear, explicit props – no hidden merges.
- Easy to share logic & data across multiple components.
- Keeps stateful logic separate from stateless presentation.
⚠️ Cons
- Deeply nested trees if you stack many render‑prop components.
- Largely superseded by Hooks (e.g.,
useQuery
,useSpring
).
8 When Should You Still Use It?
- You need to expose multiple pieces of stateful data to arbitrary markup.
- You’re supporting projects stuck on React < 16.8 (no hooks).
- You want library consumers to decide how to render but reuse what to render logic.
9 Key Take‑aways
- A render prop is just “a function that returns JSX.”
- It’s perfect for state/logic → view separation.
- Hooks may replace it in many cases, but render props are still a valuable tool in your pattern toolbox.
Feel free to copy the snippets above, fork the Codesandboxes in the original chapter, and experiment!
Content adapted from “Render Props Pattern,” Patterns.dev (CC BY‑NC 4.0).
Top comments (0)