DEV Community

Carl
Carl

Posted on • Edited on • Originally published at carlrippon.com

3 1

Render props are still useful

The render props pattern has been a popular way to share logic between components. Since React 16.8 custom hooks are a more elegant way of sharing logic between components. So, no need for render props now then? No! Render props are still useful for building reusable components ...

What is a render prop?

A render prop is a prop that is a function that renders something – i.e. a function that returns JSX:

interface Props {
...
renderItem?: (item: string) => JSX.Element;
renderHeader?: () => JSX.Element;
}
view raw List.tsx hosted with ❤ by GitHub

They can be used to delegate the rendering of bits of a component to the consumer of the component. This can make a component very flexible and highly reusable.

Every component already has a render prop!

Every React component has a children prop:

export const Card: FC = ({ children }) => (
<div className="card">
{children}
</div>
);
view raw Card.tsx hosted with ❤ by GitHub

This is a render prop! In the above example the children prop allows the consumer of the component to render the content of the card.

<Card>
<p>Some interesting text</p>
<button>Click me</button>
</Card>
view raw Index.tsx hosted with ❤ by GitHub

Above is an example of consuming the Card component. The paragraph and button elements nested inside Card are picked up as the children prop and rendered inside the card div:

Card

Creating a render prop

We can create our own render prop:

interface Props {
title?: string;
renderHeader?: () => JSX.Element;
}
export const Card: FC<Props> = ({ children, title, renderHeader }) => (
<div className="card">
<div className="card-header">
{renderHeader ? renderHeader() : title !== undefined ? title : null}
</div>
<div className="card-content">{children}</div>
</div>
);
view raw Card.tsx hosted with ❤ by GitHub

We have extended the Card component to have a header. The consumer can override default appearance using the renderHeader render prop:

<Card renderHeader={() => <h3>A custom header</h3>}>
<p>Some interesting text</p>
<button>Click me</button>
</Card>
view raw Index.tsx hosted with ❤ by GitHub

Above is an example of consuming the Card component supplying the header using the renderHeader prop. We simply assign the renderHeader prop to an inline arrow function that returns a h3 containing our title.

Card with custom header

We are now starting to understand the power of render props and how it makes a component super flexible and reusable.

Reusable list

A common use case for render props are list components:

interface Props {
data: string[];
renderItem?: (item: string) => JSX.Element;
renderHeader?: () => JSX.Element;
}
export const List: FC<Props> = ({ data, renderItem, renderHeader }) => (
<div className="list">
<div className="list-header">{renderHeader && renderHeader()}</div>
<ul>
{data.map(item => (
<li key={item}>{renderItem ? renderItem(item) : item}</li>
))}
</ul>
</div>
);
view raw List.tsx hosted with ❤ by GitHub

Above is a simple List component that has render props for the list header and list items. Notice that renderItem has a parameter for the data item to be used when rendering the item.

<List
data={["Fred", "Bob", "Jane"]}
renderHeader={() => <h3>Names</h3>}
renderItem={item => (
<div>
<span style={{ marginRight: "10px" }}>{item}</span>
<button>Click me</button>
</div>
)}
/>
view raw Index.tsx hosted with ❤ by GitHub

Above is an example of consuming the List component. We render the list header using a h3 using the renderHeader prop. We render each data item in a span with a Click me button alongside it using the renderItem prop. Below is the result:

List

Nice!

Wrap up

Render props are still really useful when we are creating highly reusable components that allow the consumer to render custom elements.

Every React component automatically has a children prop for allowing the consumer to render a single bit of the component.

We can create our own render props in a component where we want to allow the consumer to render different bits of a component.

Render props can take in parameters which is useful when the render prop is being used to render a collection of data items.

Originally published at https://www.carlrippon.com/render-props-are-still-useful on August 28, 2019.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (1)

Collapse
 
boveru profile image
boverU

Nice article! Thanks for sharing)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay