Render Props


In this article, we will discuss about Render Props in React.

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

A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.

In our Previous Videos, we have seen how do we use properties to pass data to the components and we have also seen how do we assign a callback function as value to a Property of a Component. 

Now we will be learning about Render Props in React. Lets take an example. In our React application, assume that we are displaying Departments list and Projects list. 

We have the Departments Component which is getting the data from lets say a Web API and display the data. 

We have the Projects Component which is getting the data from localStorage through a Proerty and displaying the Data. 

We have an App Component which is Calling both these Components. I have the Code handy and pasting it here.

import ReactDOM from "react-dom";

import React, { Component, Profiler } from "react";



class Department extends React.Component{

  constructor(props){

    super(props);

    this.state={

      list:['Dev','Big Data','Mobility']

    };

  }



  render(){

    return(

      <div>

        <h2>Department List...</h2>

        <ul>

          {this.state.list.map(d=>(

            <li>{d}</li>

          ))}

        </ul>

      </div>

    );

  }

}



class Project extends React.Component{

  constructor(props){

    super(props);    

  }



  render(){

    return(

      <div>

        <h2>Projects List...</h2>

        <ul>

          {this.props.list.map(d=>(

            <li>{d}</li>

          ))}

        </ul>

      </div>

    );

  }

}



class Page extends React.Component{

  constructor(props){

    super(props);

  }

  render(){

    return(

      <React.Fragment>

        <Department></Department>

        <Project list={['P-1','P-2','P-3']}></Project>

      </React.Fragment>

    )

  }

}

const element=<Page></Page>

ReactDOM.render(element,document.getElementById("root"));

If we observe both Departments Component and Projects Component, though they are getting the data from different sources and but the rendering pattern remains same. Now why cant we reuse the rendering code across multiple components. That way we will be making our code better and we will also be meeting Single Responsibility Principle as well. 

We can make One Component Responsible to get the Data and we have another component which renders the data.

Now lets take out the rendering code which is common in both the Component classes. 

Lets create a class called as DisplayData and extend it from React.Component class. Add a constructor. Lets implement render method.

Assuming that this component receives the list through properties and lets create ul, loop through the list.

class DisplayData extends React.Component{

  constructor(props){

    super(props);

  }

  render(){

    return(

      <ul>

          {this.props.list.map(d=>(

            <li>{d}</li>

          ))}

        </ul>

    );

  }

}

Lets go to Department Component Class render method, take out the code which is displaying the department data and call a method called as render using the properties object and pass the list data. We are calling a Property called as Render as a function by passing the list.

We will do the same in Project Class as well. 

<div>

        <h2>Department List...</h2>

        {this.props.render(this.state.list)}

      </div>

Then lets go to Page class, We will slightly change the way how we call Department Component. To this Department Component, we will add a Property called as render and to that render property, lets pass a function. This function receieves the list and that list should be passed to DisplayData Component class which will render the list. 

We will repeat the same for Project Component as well.

Save these changes, navigate to the browser. We can see the output. We are getting the same output but improved code reusability. 

More concretely, a render prop is a function prop that a component uses to know what to render.

It’s important to remember that just because the pattern is called “render props” we don’t have to use a prop named render to use this pattern. In fact, any prop that is a function that a component uses to know what to render is technically a “render prop”.

Basically we are calling a function which is rendering the contents of Department Component.

The Concept of Render Props is considered as one of the Design Pattern while developing a React application. 

To deepen our understanding about this concept, lets write one more example. I have copied our Employee Reports Component Class which we have created and pasting it here.

class EmployeeReports extends React.Component {

  constructor(props) {

    super(props);

    this.state = {

      employees: []

    };

  }



  componentDidMount() {

    fetch("https://localhost:44306/api/Employee")

      .then(res => res.json())

      .then(

        (result) => {

          this.setState({

            employees: result

          });

        }

      );

  }



  render() {

    return (

      <div>

        <h2>Employees Data...</h2>

        <table>

          <thead>

            <tr>

              <th>Id</th>

              <th>Name</th>

              <th>Location</th>

              <th>Salary</th>

            </tr>

          </thead>

          <tbody>

          {this.state.employees.map(emp => (

            <tr key={emp.Id}>

              <td>{emp.Id}</td>

              <td>{emp.Name}</td>

              <td>{emp.Location}</td>

              <td>{emp.Salary}</td>

              </tr>

          ))}

          </tbody>

        </table>

      </div>

      );

    }

}

Now lets create a new Component class called as DisplayEmployees. Add the constructor and we will keep the code of displaying the Employees in the render method.

Now lets go to EmployeeReports Component Class render method and call render property by passing employees list.

Now lets call the EmployeeReports Component, pass render property and assign a function. This function receives employees data and pass that to DisplayEmployees Component through a property and that Component renders the Employees Data.

With Render Props:

class DisplayEmployees extends React.Component{

  constructor(props){

    super(props);

  }



  render(){

    return(

      <table>

          <thead>

            <tr>

              <th>Id</th>

              <th>Name</th>

              <th>Location</th>

              <th>Salary</th>

            </tr>

          </thead>

          <tbody>

          {this.props.employees.map(emp => (

            <tr key={emp.Id}>

              <td>{emp.Id}</td>

              <td>{emp.Name}</td>

              <td>{emp.Location}</td>

              <td>{emp.Salary}</td>

              </tr>

          ))}

          </tbody>

        </table>

    )

  }

}

class EmployeeReports extends React.Component {

  constructor(props) {

    super(props);

    this.state = {

      employees: []

    };

  }



  componentDidMount() {

    fetch("https://localhost:44306/api/Employee")

      .then(res => res.json())

      .then(

        (result) => {

          this.setState({

            employees: result

          });

        }

      );

  }



  render() {

    return (

      <div>

        <h2>Employees Data...</h2>

        {this.props.content(this.state.employees)}

      </div>

      );

    }

}

const element=<EmployeeReports content=

                  {(input)=><DisplayEmployees employees={input}></DisplayEmployees>}>                    

                  </EmployeeReports>

ReactDOM.render(element,document.getElementById("root"));

Video Reference:





© 2020 Pragimtech. All Rights Reserved.