Render Props – An Advanced React Pattern
Being a programmer, you always need to find the easiest way to solve a problem – write succinct and reusable code that other developers can quickly grasp. Currently, UI libraries like react.js, vue.js etc. are very popular because one can write reusable code while solving complex UI problems. Development is fast and it makes life easy for everyone.
Design patterns are fairly common and popular. React also has its own set of patterns which aid in writing clean and robust code while keeping it maintainable. We will be exploring these patterns through a series of blogs.
First off, we will be starting with Render props which is one of hottest topics in react community. We will also be building an entire app to see Render Props in action. Happy reading!

Table of Contents
- What is render props?
- Let’s understand render props in depth.
- Have you checked the babel transpiled version of render props?
- Sample App – Posts and Comments
- 1. Building the app without Render Props
- 2. Creating a new component “Wrapper”
- 3. Posts & Comments – Render Method
- 4. Sample App with Render Props
- Conclusion
What is render props?
As mentioned in the react docs:
The term “render prop” refers to a technique for sharing code between React components using a prop whose value is a function.
In simple words, render props are simply props of a component where you can pass functions. These functions need to return elements, which will be used in rendering the components.
Let’s understand render props in depth.
Render props look like this:
class NameWrapper extends Component {
state = {
name: 'Dan Abramov'
};
render() {
return this.props.render(this.state.name);
}
}
const Name = () => (
<NameWrapper render={name => <h2>Hi, {name}!</h2>} />
);
We are using the “Name” component where we can pass a prop called render. Here, render is a function and it receives an argument i.e. state “name”.
The babel version of JSX looks like this:
const App = () => {
return (
<SomeParent>
<SomeChild/>
</SomeParent>
);
}
Have you checked the babel transpiled version of render props?
Let’s see how the “Name” component will look in Babel Repl:
var Name = function Name() {
return React.createElement(
NameWrapper,
{
render: function render(name) {
return React.createElement(
"h2",
null,
"Hi, ",
name,
"!"
);
}
}
);
};
As you can see, instead of passing down any value to the props i.e. render, we are passing a function here. So, when that function gets called we will get the <h2> element with the message “Hi, Dan Abramov!”.
As promised, we will now go ahead to an app applying what we have learnt about Render Props.
Sample App – Posts and Comments
In our sample app:
- We have posts with title, description and a link to get the comment for that blog.
- By clicking on “View Comment”, we will get the comments section.
1. Building the app without Render Props
The code for the app would look something like this:
Pro Tip – We have taken help of JSONPlaceholder for fake rest API call. You can use it for testing and prototyping. Do check it out!
There are 2 files that we need to look at:
- Post.js
- Comment.js
Observe that we have a lot of duplicate code like state object, componentDidMount() and getData(). These objects and methods are doing almost the same thing in <Post/> and <Comment/> components. This clearly goes against the DRY principle. Instead, we can write common code which can be shared by both <Post/> and <Comment/> by creating a new component.
2. Creating a new component “Wrapper”
import React from "react";
import axios from "axios";
class Wrapper extends React.Component {
state = {
data: null,
error: null,
isLoading: true
};
getData() {
axios.get(this.props.link)
.then(response => {
this.setState({
data: response.data,
isLoading: false
});
})
.catch(error => {
this.setState({
error,
isLoading: false
});
});
}
componentDidMount() {
this.setState({ isLoading: true }, this.getData());
}
render() {
return this.props.render(this.state);
}
}
export default Wrapper;
As you can see, we have extracted state object, getData() and componentDidMount() from both the components and put it in the Wrapper component. Inside the render of Wrapper component we are calling this.props.render() with an argument state and returning it.
Now, let’s see the render method of Post and Comment components.
3. Posts & Comments – Render Method
render() {
return (
<Wrapper
link="https://jsonplaceholder.typicode.com/posts"
render={({ data, error, isLoading }) => (
<div>
<h2>User Post</h2>
{error && <p>{error.message}</p>}
{isLoading ? (
<h5>Loading....</h5>) : (
<ul>
{data.map(post => (
// Code for posts
))}
</ul>
)}
</div>
)}
/>
);
}
render() {
return (
<Wrapper
link={this.props.link}
render={({ data, error, isLoading }) => (
<div>
<h4>Comment</h4>
{error && <p>{error.message}</p>}
{isLoading ? (
<h5>Loading....</h5>) : (
<div>
<p className="comment">{data.body}</p>
<div>
<span className="by">Commented By:</span>
<span className="name">{data.name}</span>
</div>
</div>
)}
</div>
)}
/>
);
}
In the Wrapper component, we are passing props called “render”. It catches the state arguments and returns an element in which values of these arguments are used.
4. Sample App with Render Props
Finally, here is the complete solution using render props:
Conclusion
We saw how Render Props helped us avoid duplicate code and create a more robust app. Clearly, there is merit in applying Render Props to your next app. React’s latest context API uses render props. Even Apollo client uses it. Developers are increasingly accepting render props and all we are saying is you should definitely give it a try!