DEV Community

Cover image for Demystifying React Render Props: A Beginner's Guide
MuneebChaudhry-dev
MuneebChaudhry-dev

Posted on

Demystifying React Render Props: A Beginner's Guide

React is a powerful JavaScript library that has changed the way developers think about building UI for web applications. One of its most powerful features is the ability to use Render Props to create reusable and flexible components. In this article, we will take a deep dive into what Render Props are and how they can help you write cleaner, more modular code.

What are Render Props?

According to React Documentation:

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

So basically,Render Props are one of the design pattern in React which is a way of sharing code between components in React. They allow you to create a component that can be used in multiple places, with different rendered outputs. Instead of hard-coding the output in the component, you pass a function as a prop that will generate the desired output. This function is then referred to as the Render Prop.

Why Use Render Props?

The main advantage of Render Props is that they allow you to create reusable components that can be used in multiple places, with different outputs each time. This makes it easy to write clean, modular code that is easy to maintain and extend.
Another advantage of Render Props is that they provide a way to share state and logic between components. This can be especially useful when you want to implement complex UI logic, such as managing form inputs or displaying animations. With Render Props, you can isolate this logic in a single component, and then share it across multiple parts of your application.

How to Use Render Props in React?

Using Render Props in React is simple and straightforward. All you need to do is create a component that accepts a Render Prop, and then use that Render Prop to determine what to render. Here’s an example of a simple component that uses a Render Prop:

const User = ({ name() }) => {

  return name("Guest");
};
export default User;
Enter fullscreen mode Exit fullscreen mode

In this example, the component accepts a single prop called “render”, which is a function that generates the output for the component. The component then calls this function, passing in its state, to determine what to render.

To use this component in your application, you would pass a Render Prop as a prop to the component:

<User
name={() => (
    <div>
      <h1>My Component</h1>
      <p>{state.message}</p>
    </div>
  )}
/>
Enter fullscreen mode Exit fullscreen mode

In this example, the Render Prop is a function that returns a JSX element. This JSX element is then used to render the component.

Note: While the term "render" was used as a render prop in the above code, it's important to note that you can use any name for a render prop. In other words, using the name "render" is not a requirement.

Practice

Chellange:

let create a chellange to understand the essence of this patterns. This challenge will be simple, so we can focus on the core concepts. To start, we'll take a look at a component:

interface Props {
  isLoading: boolean;
  data: IData[];
}

const Employee = ({ isLoading, data }: Props) => {
  if (isLoading) {
    return <div>Loading...</div>;
  }
  return (
    <>
      {data?.map((item) => (
        <div key={item.id}> {item.name}</div>
      ))}
    </>
  );
};

Enter fullscreen mode Exit fullscreen mode

As developers, we can observe that the Employee component violates the Single Responsibility Principle. The primary function of the Employee component should only be to display a list of employee. However, the component also handles rendering fallback i.e. when the data is loading to list the employee. Additionally, we may have multiple instances of the Employee component in our app that require handling of these same fallback (such as for TodoList or InventoryList). To avoid repetition, we need to find a way to eliminate these redundancies.

Render Props pattern helps us here. Let’s start implementing the pattern.

Solution

We should adhere to this structure and generate a distinct component for Render Props that pertains to the aforementioned challenge. The role of this Render Props component is to display a fallback while the data is being loaded.

interface Props {
  loading: boolean;
  children: JSX.Element;
}

const Loading = ({ loading, children }: Props): JSX.Element => {
  return loading ? <div>Loading ...</div> : children;
};

export default Loading;
Enter fullscreen mode Exit fullscreen mode

The use of Loading component then looks like this:

interface Props {
  isLoading: boolean;
  data: IData[];
}

const Employee = ({ isLoading, data }: Props) => {
  return (
    <Loading loading={isLoading}>
      <>
        {data?.map((item) => (
          <div key={item.id}> {item.name}</div>
        ))}
      </>
    </Loading>
  );
};
export default Employee;
Enter fullscreen mode Exit fullscreen mode

In this code, you can observe that our render prop can be any JSX element. In this instance, it is the children element that we pass to the Loading component, which in turn also returns a JSX element.

Conclusion

Render Props are a powerful feature of React that allow you to create reusable and flexible components. They make it easy to write clean, modular code that is easy to maintain and extend, and provide a way to share state and logic between components. If you’re looking to take your React skills to the next level, learning about Render Props is a great place to start.

Top comments (1)

Collapse
 
jangeroo profile image
Michael Jang

This is a good and clear explanation of how to split the code along lines of responsibility, but I'm not sure it's clear in the challenge example how this illustrates the concept of "render props". As you mentioned from the React documentation, "render props" is "a technique for sharing code between React components using a prop whose value is a function". Your example, however, doesn't take a function as a prop; it simply conditionally renders the loading state or the children. Can you clarify how you see this as an example of "render props"?