Hi everyone, my name is Javen and I'm a front end engineer at ZEALS. Today I'm gonna teach you about Render Props!!
What are Render Props?
The term “render prop” refers to a simple technique for sharing code between React components using a prop whose value is a function.
Render Props is a React pattern that has gained a lot of attention over the past year or so. Many React engineers have gone through debates on whether High Order Components (HoC) or Render Props are better for their applications. When all is said and done, both patterns are great but each have their own pros and cons. However, today I'm going to discuss Render Props!
This is an example of a render prop component:
<MyRenderProp render={({ data }) => ( <h1>Hi I'm a Render Prop Component! Here is my data: {data}</h1> )} />
As you can see in this component, "MyRenderProp", there is a "render" prop that is getting passed down. In this prop, there is a function that returns an <h1>
element which renders out "data". "data" is a parameter that gets passed to that function. This is the basic gist of a Render Prop component.
When to use Render Props
It's really hard to know when to use a specific React pattern. It usually takes some experience and practice with multiple variations of components to know which pattern to use.
As for Render Props, it is suggested that whenever you want to be able to share state and/or behaviors that are encapsulated by the component, then you should want to use a Render Prop component.
Example in code
I will continue from the above (finished) example in order to demonstrate the effectiveness of Render Props. So in the example above, there is a component called "MyRenderProp" which wants to display some data with the <h1>
element. But right now we don't know what that data and "MyRenderProp" looks like, so I will show it in the code below! 😅
import React from 'react'; class MyRenderProp extends React.Component { state = { data: 50 }; handleIncrement = () => this.setState({ data: this.state.data + 1 }); handleDecrement = () => this.setState({ data: this.state.data - 1 }); render() { return ( <div> {this.props.render({ ...this.state })} <button onClick={this.handleIncrement}>Increment 👆</button> <button onClick={this.handleDecrement}>Decrement 👇</button> </div> ); } }
In this code, we want to be able to share the value of "data". To achieve this, we can use this.props.render
as a function to pass the "data" state to whatever gets rendered through the "render" prop!
Let's see this component in action!!! 😏🙃
function App { return ( <div> <MyRenderProp render={({ data }) => ( <h1>Hi I'm a Render Prop Component! Here is my data: {data}</h1> )} /> <MyRenderProp render={({ data }) => ( <p>The percentage of people using Render Props: {data}%</p> )} /> </div> ); }
As you can see, "MyRenderProp" is fully reusable to anything that needs an increment/decrement button with some related data attached to it!
🎉And that's it! Our Render Props component is fully implemented! 🎉
However, there is another way to write this piece of code in a much nicer, cleaner, and readable way! (Well... at least it is to me...😅)
In our "MyRenderProp" component render function: render() { return ( <div> {this.props.children({ ...this.state })} <button onClick={this.handleIncrement}>Increment 👆</button> <button onClick={this.handleDecrement}>Decrement 👇</button> </div> ); }
In our "App" component return function: return ( <div> <MyRenderProp> {({ data }) => ( <h1>Hi I'm a Render Prop Component! Here is my data: {data}</h1> )} </MyRenderProp> <MyRenderProp> {({ data }) => <p>The percentage of people using Render Props: {data}%</p>} </MyRenderProp> </div> )
Two things changed:
- In the "MyRenderProp" component,
this.props.render
got changed tothis.props.children
. - The "render" prop function on "MyRenderProp" got moved in between the opening and closing tags of "MyRenderProp".
Anything in between the opening and closing tags of a component can be considered a child of that component. That is why we can remove the "render" prop and replace this.props.render({ ... })
with this.props.children({ ... })
! And it will still work the same way! 👍You can decide which one you want to use. There is always more than one right way to do finish the job!
Conclusion
This was a simple example that could have been implemented in many other ways, but the purpose was to show how Render Props works. I hope you got a better understanding of what Render Props are and how to use them. If you did, try it out for yourself next time you want to make a reusable component! Also if you need better explanations, I recommend you to read the React docs. I think it explains Render Props more in-depth than I did! 😂The docs and codesandbox should be linked at the bottom of this article.
Thank you for your time! Peace! ✌️
Javen