An introduction to render props

The render props pattern is a way to share functionality between components without repeating code. The official React docs define it as —

The term “render prop” refers to a simple technique for sharing code between React components using a prop whose value is a function.

<DataProvider render={data => (

<h1>Hello {data.target}</h1>

)}/>

By using a prop to define what is rendered, the component just injects functionality without needing to know how it is being applied to the UI. Let’s take a look at an example to understand what this actually means.

The render props pattern

Render props means that you pass a render function defined by a separate component’s props to indicate what should be returned by the shared component. At its root level, it must take the form:

this.props.render() is a function passed in by another component. This function itself should return a React component. The simple render prop we created above just wraps the element in a <div> . To utilize the <SharedComponent /> we would do the following:

It’s also worth noting that the name of the prop does not need to be render . All that is important is that it returns a React element. For example, we could rename the prop above to be wrapThisThingInADiv , and it would still function the exact same.

A simple render prop component by example

Now that we have established the render prop pattern, let’s utilize it to actually share some functionality between components. We will create a component to inject data in the component being rendered via the render prop function.

Our team has figured out the secretToLife which turns out to be the number 42 . Some of our components need to share this information, and we can create a render prop component called ShareSecretToLife to pass it to our components.

Here we pass the secretToLife as a parameter to our render prop function. This allows us to use the value in the returned React component as well — in this instance displaying a bold 42 inside an <h1> .

A practical render prop component by example

Now that we understand how to share data and functionality with render props, we can build one with practical implications. Since a render prop component is just that, a component, we have access to the entire React API such as lifecycle methods and component state.

The functionality of our <Storage /> component will be to save/load the state of a component with localStorage , allowing us to quickly access and render it on a page load. Then it will share this functionality via render props. This gives it the following form:

At the top of <Storage /> we have a single item in the component’s state which tracks if localStorage is available in the given browser. We use the componentDidMount lifecycle hook which will check if localStorage exists via the checkLocalStorageExists function. Here it will test saving an item and set the state to true if it succeeds.

We also add three functions to our component — load , save , and remove . These are used to directly access the localStorage API if it is available. Our three functions on the component are passed to render prop function.

Now we will create a new render component to utilize in our shared <Storage /> component which allows it to gain the storage functionality. It will be used to display a user’s username and favorite movie. However, the API call to get this information takes a very long time. We can also assume that these values will never change once set.

To ensure we have a great user experience, we will make this API call only if the values have not been saved to localStorage . Then every time the user returns to the page, they can access the data immediately instead of waiting for our API to return.

Our shared <Storage /> injects the save and load which are used by <ComponentNeedingStorage /> . First we check if the username and favoriteMovie exist by trying to load them from storage or the component state. If they do not exist, we will make our reallyLongApiCall which is called inside fetchData . We want to make sure that we only call this function once, so we also manage an isFetching variable. Once the data has either been loaded from localStorage or returned from the API call, we then display them to the user.

Wrap up

Render props is a powerful pattern to allow developers to share functionality between components. It enables us to keep our code DRY and extract methods into a common location

Render props are often compared to higher-order components since they serve a similar purpose. If you’re interested in learning more about higher-order components check out my other article where I build the same storage functionality.