If you’ve used React for a while, you might have heard about Render Props already. Similar to Higher Order Component, it provides a layer of indirection. The idea is to pass a function as a prop to a component, and the component that receives this prop will call the prop in its render method.
At a glance, this may seem confusing, so I’m going to show you a step by step walkthrough from a simplest normal props with a static value to render props.
Step 1. pass in normal props
A Data component that has an render prop, and when this props get called, it just console log the prop value
<Data render='data' />--> function Data (props) {
const render = props.render // data
}
Step 2. replace the normal prop of static value with a simple function
Now we replace the render='data'
with a function render={() => 'data'}
And when it’s get rendered this function gets called when we call the prop. And we get the same result.
<Data render={() => 'data'} />--> function Data (props) {
const render = props.render) // data
}
Step 3. upgrade the simple function to receive argument
Here we let the simple function render={() => 'data'}
to receive an argument. So now when we call the props in the render method, we also pass in an argument ( true
) .
<Data render={(isLoaded) => isLoaded === true ? 'data' : null} />
function Data (props) {
const render = props.render(true) // data
}
Step 4. pass state as argument to the function props and call it in component’s render method
Now replace the functional with a class component, now we have a render method if Data component that will call the render
props and pass in its isLoaded
state as an argument; the render
props then get passed in a function that will render a HTML based on the boolean value of the passed-in argument.
<Data render={
(isLoaded) =>
<div> {isLoaded === true ? ‘data’ : null} <div>
} />class Data extends React.Component (props) {
state = { isLoaded: true }
render(){
{this.props.render(this.state.isLoaded)} // data
}
}
Step 5. change the passed in function to a component
Now we are pretty close to the final step. What we will do now is to change the <div> {isLoaded===true ? “data" : null} </div>
from a simple HTML to a proper component. So you will see this component will receive the isLoaded
status from the Data component.
class Data extends React.Component (props) {
state = { isLoaded: true }
render(){
{this.props.render(this.state.isLoaded)} // data
}
}function LoadData (props) {
return (
<>
{props.isLoading === true
? "THE DATA IS LOADED!"
: null}
</>
)
}function App () {
return (
<>
<Data render={(isLoaded) =>
<LoadData isLoading={isLoaded}>
}/>
</>
)
}
Note that class component Data
is not absolutely necessary. We can of course change it to a functional component with a useState
hook
const Data = (props) => {
const {render} = props
const [isLoaded, setIsLoaded]= React.useState(true) return(
{render(isLoaded)}
)
}
Also note that you don’t necessarily need to use the “render” props. In fact, you can use any props as you wish. It’s just a convention that is good to follow to use “render”.
class Data extends React.Component (props) {
state = { isLoaded: true }
render(){
{this.props.callItAnything(this.state.isLoaded)} // data
}
}function App () {
return (
<>
<Data callItAnything={(isLoaded) =>
<LoadData isLoading={isLoaded}>
}/>
</>
)
}
That’s a little piece about render props
pattern. Enjoy :).