Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

Subscribe to the newsletter

Get new articles and course lessons delivered to your inbox. No spam, unsubscribe anytime.

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 16 of the Advanced React: Performance, Architecture & Patterns course
ReactJune 27, 20264 min read

Mastering the Render Props Pattern for Advanced Logic Reuse

Learn how to use Render Props in React to share complex logic across your application while keeping your UI components decoupled, flexible, and highly reusable.

ReactPatternsLogic ReuseComponent ArchitectureRender Propsjavascriptfrontend

Previously in this course, we explored Designing Compound Components: Advanced React Architecture Patterns to manage implicit state within a shared interface. While compound components are excellent for structural cohesion, sometimes you need to share pure behavioral logic without imposing a specific DOM structure. This is where the Render Props pattern shines.

Understanding Render Props from First Principles

In React, the "Render Props" pattern refers to a technique where a component receives a function as a child (or a specific prop) that returns a React element. Instead of the component deciding what to render, it delegates that responsibility to the consumer, while providing the consumer with the state or logic it needs.

Think of it as an "Inversion of Control" mechanism. The component acts as a stateful "engine"—handling events, data fetching, or timers—and passes the engine's output to the function provided by the parent.

Worked Example: A Reusable Mouse Tracker

Let’s build a component that tracks mouse coordinates. We want to reuse this logic in different parts of our dashboard without locking the UI into a specific <div> or layout.

JSX
// MouseTracker.js
import { useState } from CE9178">'react';

const MouseTracker = ({ children }) => {
  const [coords, setCoords] = useState({ x: 0, y: 0 });

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

  // We call the function passed in CE9178">'children' with our state
  return (
    <div onMouseMove={handleMouseMove} style={{ height: CE9178">'100vh' }}>
      {children(coords)}
    </div>
  );
};

// Usage
const App = () => (
  <MouseTracker>
    {(coords) => (
      <h1>
        Mouse is at {coords.x}, {coords.y}
      </h1>
    )}
  </MouseTracker>
);

In this example, MouseTracker doesn't know what the UI looks like; it only knows how to track the mouse. This allows us to swap the <h1> for a custom tooltip, a graph, or any other component without touching the tracker logic.

Managing State Exposure and Composition

When you build these patterns, you must be intentional about what you expose. Over-exposing internal state can lead to tight coupling, making it harder to refactor the logic later.

As we discussed in State Colocation Strategies: Optimizing React Component Architecture, keeping state close to where it's used is vital. With Render Props, you are essentially "lifting" the state into the wrapper component.

Comparison: Hooks vs. Render Props

FeatureRender PropsCustom Hooks
Logic ReuseExcellentExcellent
UI FlexibilityHighHigh
ReadabilityCan lead to nesting ("Wrapper Hell")Flatter component tree
Best ForComplex UI injection logicStandard logic/data extraction

While hooks have largely replaced render props for data fetching (e.g., useSWR), render props remain superior when the shared logic must return a specific UI wrapper (like an event listener container) or when you want to provide a declarative API for complex components.

Hands-on Exercise

Refactor the following snippet. Currently, the Toggle component is hardcoded to render a button. Change it into a Render Prop component so the user can decide whether to render a checkbox, a custom switch, or a simple text link.

Initial Code:

JSX
const Toggle = () => {
  const [on, setOn] = useState(false);
  return (
    <button onClick={() => setOn(!on)}>
      {on ? "ON" : "OFF"}
    </button>
  );
}

Goal: Create a version that allows usage like:

JSX
<Toggle>
  {(on, toggle) => <input type="checkbox" checked={on} onChange={toggle} />}
</Toggle>

Common Pitfalls

  1. The "Wrapper Hell" Trap: If you compose multiple render-prop components, your JSX will nest deeply. If you find yourself in this situation, consider if a custom hook can extract the logic instead, or use a "Compose" utility to flatten the tree.
  2. Performance Issues: If the render function is defined as an anonymous function inside the parent's render cycle (like in the examples above), it will be recreated on every re-render. If the Render Prop component is memoized, this will break the optimization. Always use useCallback for the render function if you are passing it to a React.memo wrapped component.
  3. Forgetting Types: If you are using TypeScript, ensure your render prop function is typed correctly to avoid any types when accessing the shared state.

Recap

Render Props provide a powerful way to share logic while maintaining structural flexibility. By inverting control, you allow consumers to define the UI while your component manages the stateful behavior. Use them when you need to provide a reusable container with specific lifecycle or event-handling behavior that isn't easily achieved through simple composition.

Up next: We will dive into Implementing Control Props, where we'll learn how to synchronize internal component state with external props for creating truly professional-grade UI primitives.

Previous lessonDesigning Compound ComponentsNext lesson Implementing Control Props
Back to Blog

Similar Posts

ReactJune 27, 20263 min read

Designing Compound Components: Advanced React Architecture Patterns

Master Compound Components in React to build flexible, intuitive UI APIs. Learn to share implicit state and enforce structure without the mess of prop drilling.

Read more
ReactJune 27, 20264 min read

State Colocation Strategies: Optimizing React Component Architecture

Master State Colocation to stop unnecessary re-renders. Learn to move state as close as possible to its consumption point for high-performance React apps.

Part of the course

Advanced React: Performance, Architecture & Patterns

advanced · Lesson 16 of 47

  1. 1

    Deep Dive into the Reconciliation Algorithm

    4 min
  2. 2

    Profiling with React DevTools

    3 min
  3. 3

    Establishing Performance Budgets

    3 min
Read more
ReactJune 27, 20263 min read

Strategic use of React.memo: Advanced Component Optimization

Master React.memo to stop unnecessary re-renders. Learn when to memoize, how to write custom comparison functions, and why over-memoization hurts performance.

Read more
  • 4

    Strategic use of React.memo

    3 min
  • 5

    Mastering useCallback and useMemo

    4 min
  • 6

    State Colocation Strategies

    4 min
  • 7

    Optimizing Context Providers

    4 min
  • 8

    Advanced Context Composition

    4 min
  • 9

    Eliminating Prop Drilling

    4 min
  • 10

    Introduction to Concurrent React

    4 min
  • 11

    Non-blocking UI with useTransition

    4 min
  • 12

    Handling Deferred Data with useDeferredValue

    3 min
  • 13

    Mastering Suspense for Data Fetching

    4 min
  • 14

    Streaming Server-Side Rendering

    3 min
  • 15

    Designing Compound Components

    3 min
  • 16

    The Render Props Pattern

    4 min
  • 17

    Implementing Control Props

    4 min
  • 18

    Headless UI Architectures

    3 min
  • 19

    Modular Directory Structures

    3 min
  • 20

    Refactoring Monolithic Components

    3 min
  • 21

    Optimistic UI Updates

    3 min
  • 22

    Advanced Cache Invalidation

    4 min
  • 23

    Handling Race Conditions

    4 min
  • 24

    Server-Client State Synchronization

    3 min
  • 25

    Route-level Code Splitting

    4 min
  • 26

    Offloading Tasks with Web Workers

    3 min
  • 27

    Advanced Error Boundaries

    3 min
  • 28

    Monitoring Production Performance

    4 min
  • 29

    Final Project Audit & Optimization

    Coming soon
  • 30

    Advanced Hook Patterns

    Coming soon
  • 31

    Managing Global State with Zustand/Redux

    Coming soon
  • 32

    Testing Performance-Critical Components

    Coming soon
  • 33

    Static Site Generation (SSG) Patterns

    Coming soon
  • 34

    Internationalization (i18n) Architecture

    Coming soon
  • 35

    Accessibility (a11y) in Advanced Components

    Coming soon
  • 36

    Managing Third-Party Integrations

    Coming soon
  • 37

    Advanced Form Handling

    Coming soon
  • 38

    Using Portals for UI Overlays

    Coming soon
  • 39

    Implementing Virtualized Lists

    Coming soon
  • 40

    Building Design System Primitives

    Coming soon
  • 41

    Managing Large-Scale Data Fetching

    Coming soon
  • 42

    Micro-Frontends with React

    Coming soon
  • 43

    Security Best Practices in React

    Coming soon
  • 44

    Advanced Ref Usage

    Coming soon
  • 45

    Memoization Pitfalls

    Coming soon
  • 46

    Mastering React Patterns for Scalability

    Coming soon
  • 47

    Advanced TypeScript with React

    Coming soon
  • View full course