REACT Render Props

A Render Prop is a pattern for sharing code between React components using a function that returns a React element.

A component that uses a render prop expects a function as a prop, and this function returns a React element.

 

Render Prop Pattern Example

const MyComponent = ({ render }) => {
  return (
    <div>
      {render("Hello from render prop!")}
    </div>
  );
};

const App = () => {
  return (
    <MyComponent render={(message) => <h1>{message}</h1>} />
  );
};

export default App;

Try It Now

In this example:

  • MyComponent accepts a render prop, which is a function.
  • This function is invoked with the message "Hello from render prop!", and the resulting <h1> element is rendered inside the MyComponent.

1. Why Use Render Props?

Render props are a pattern used to:

  • Share functionality: Reuse logic across components by passing a function to define the rendering.
  • Customizable UI: Allow the consumer component to define how things should look by controlling what gets rendered.
  • Flexibility: Enable passing props and logic between components without directly modifying the child component.

2. Practical Example of Render Props

A. Mouse Tracker Example

Let’s say you want to track mouse position in a component and share that logic across multiple components.

 

Step 1: Create a Mouse Tracker Component

import React, { Component } from "react";

class MouseTracker extends Component {
  state = {
    x: 0,
    y: 0,
  };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY,
    });
  };

  render() {
    return (
      <div
        style={{ height: "100vh", border: "1px solid black" }}
        onMouseMove={this.handleMouseMove}
      >
        {this.props.render(this.state)} {/* Render prop is called here */}
      </div>
    );
  }
}

export default MouseTracker;

Try It Now

Step 2: Use Mouse Tracker in Another Component

import React from "react";
import MouseTracker from "./MouseTracker";

const App = () => {
  return (
    <MouseTracker
      render={({ x, y }) => (
        <h1>
          Mouse position: ({x}, {y})
        </h1>
      )}
    />
  );
};

export default App;

Try It Now

What happens?

  • MouseTracker tracks mouse movement and updates the x and y coordinates.
  • The App component receives the render prop and renders the coordinates within an <h1> tag.
  • This pattern allows any parent component to define how mouse position should be displayed.

3. When to Use Render Props?

You might want to use render props when:

  • You have shared logic that you want to inject into multiple components without changing the component structure.
  • You need customized rendering in child components.
  • You need to pass state or callbacks down to child components that control rendering.

 

4. Avoiding Prop Drilling with Render Props

In deep component trees, prop drilling (passing props from parent to deeply nested children) can be cumbersome. Render props can help avoid this by centralizing logic in a higher component.

Example: Using Render Prop to Avoid Prop Drilling

Let’s say you have several nested components, and you want to pass data from the top level without prop drilling.

const ParentComponent = () => {
  const userData = { name: "John", age: 30 };
  return (
    <ChildComponent render={(data) => <GrandchildComponent user={data} />} />
  );
};

const ChildComponent = ({ render }) => {
  const data = { name: "Alice", age: 25 };
  return render(data);
};

const GrandchildComponent = ({ user }) => {
  return <div>{user.name} is {user.age} years old.</div>;
};

Try It Now

This avoids deep prop drilling and keeps your code cleaner.

5. Performance Considerations

While render props provide flexibility, it can sometimes result in unnecessary re-renders, especially if the function passed to the render prop changes on every render. To optimize performance:

  • Use React.memo: If the rendered output is the same and doesn’t need to change.
  • Use useCallback: To memoize the render function passed to the render prop, preventing unnecessary re-renders.