Render Props

— what, how, why, and when we should use it?

Leanne Z
3 min readSep 4, 2018

1) What is a render prop?

“render prop” is a design pattern. It simply means that the component has a render prop that takes in a function as a value, and the component uses that function to render whatever the function provides.

Chances are you already have used render props without knowing it. Considering React-router library, <Route /> holds the behavior of navigating to different pages. It renders the component when the path matches.

<Route path='/page' component={Page} />const extraProps = { color: 'red' }<Route path='/page' render={(props) => (
<Page {...props} data={extraProps}/>
)}/>

As you can see in this example, <Route /> takes in a function which renders the Page component.

Note: you can use any prop name other than “render” to takes in a function.

2) Why is it useful?

This pattern is very useful when we want to share the same behavior among different components minimizing code repetitions.

3) How does it work?

I’m going to write a simple example using local states, then rewrite it using renderProp so you can see clearly the benefits of using render props.

Let’s first see how you can implement a ToDoList with local React states.

Here, you have 2 states:

  • tasks: holds a list of tasks
  • newTask: hold a task description

Event handlers which can add, change, and mark task as completed:

  • handleChangeTask
  • handleClickAdd
  • handleClickDone

View full code here

What if we have other components that need the same behavior like to add, delete, and change item in a list?

This is where render prop comes in handy.

To reuse the logic in the ToDoList, let’s rename ToDoList to ListManipulator. ListManipulator only holds the behavior to add, delete, and change item; we decouple the UI from the states making the ListManipulator component reusable.

ListManipulator.jsx

export default class ListManipulator extends React.Component {  static propTypes = {
render: PropTypes.func.isRequired
};
state = {
items: [],
newItem: ""
};
// event handlers here... render() {
const { render } = this.props;
return render({
...this.state,
done: this._handleClickDone,
add: this._handleClickAdd,
change: this._handleChangeItem
});
}
}

Then, we use this.props.render to dynamically determine what to render. For example, this.props.render can render a shopping list, a goal list, or any kind of component that may need to add, delete, or change an item from a list.

App.jsx

import ListManipulator from "./ListManipulator";export default class App extends React.Component {  shoppingList = ({ items, newItem, done, add, change }) => {
return (
// render shopping list here ..
<div>{items}</div>
)
}
goalList = ({ items, newItem, done, add, change }) => {
return (
// render goal list here ..
<div>{items}</div>
)
}
render() { return ( <div> <h1>My Dashboard </h1> <div className="Dashboard">
// a render prop function gives us the states from ListManipulator and we can use to display whatever we want
<ListManipulator render={this.goalList} /> <ListManipulator render={this.shoppingList} /> </div> </div>); }}

→ See the full working code on my codesandbox.

4) When should we use Render Prop? How is it different from Redux pattern?

Redux holds our states in one place, which makes reading and updating global states predictable. It is an additional library that we will need to import.

However, render prop reads and updates with React local states. If you want to reuse component logic and separate UI from the states, consider using a render prop. For example, building a custom reusable library.

Here are some example of libraries which use render props from Jared Palmer! Go poke around and have fun with them.

https://github.com/jaredpalmer/awesome-react-render-props

I’m curious how you use render props. :) I would love to hear your feedback.

--

--