React has rapidly become one of the most popular JavaScript libraries for building fast, interactive user interfaces. Its component-based architecture like React HOC, Render Props and Hooks, combined with a robust ecosystem of tools and capabilities, makes React a go-to choice for many web development teams.

However, as React applications grow in size and complexity, developers need strategies for effectively sharing stateful logic between components. React provides several advanced component patterns that allow more code reusability and abstraction without compromising understandability or performance.

In this article, we’ll explore three advanced React component patterns— React HOCs (higher-order components), render props, and Hooks—including real-world code examples of each. We’ll discuss the use cases where these patterns shine and offer actionable tips for implementing them in your own React projects.

React HOC (Higher-Order Components)

React Higher order components (HOCs) allow you to create reusable container components that wrap and provide additional functionality to other React components. HOCs work as component transformers by taking in a component and outputting a new enhanced component. 

interface WrappedComponentProps {
  // ...
}function withMouse(
  WrappedComponent: React.ComponentType<WrappedComponentProps>
) {
  return class extends React.Component {
    state = { x: 0, y: 0 }
    
    handleMouseMove = (event: MouseEvent) => {
      this.setState({
        x: event.clientX,
        y: event.clientY
      });
    }

    render() {
        return (
          <WrappedComponent
            {...this.props}
            mouse={this.state}
          />
        );
    }
  }
}

Usage:

const MousePosition = () => (
  <div>
    X: {this.props.mouse.x}, Y: {this.props.mouse.y}
  </div>
);

const MousePositionWithMouse = withMouse(MousePosition);

<MousePositionWithMouse />

Benefits

  • Avoid duplication – Share logic between components without repeating code.
  • Decoupled code – HOC logic stays separate from wrapped components
  • Easy to compose – Chain together multiple HOCs on a single component

Use cases

  • Data fetching – Fetch data once and provide it to many components
  • State management – Connect components to external stores.
  • Element styling – Add styling hooks for consistent looks

Tips

  • Don’t overuse HOCs – They increase complexity and indirection.
  • Give concise names – Clearly indicate added functionality.
  • Lift state up carefully – Avoid performance issues with excessive passing down

React Render Props

The “render props” pattern refers to React components that use a prop whose value is a function to allow flexible, dynamic children content. Instead of hard-coding what gets rendered inside a component, you can dynamically determine it using an injected render prop.

interface RenderPropComponentProps {
  // ... 
}

interface RenderPropComponentState {
  // ...
}

class Mouse extends React.Component<
  RenderPropComponentProps, 
  RenderPropComponentState
> {

  // ...

  render() {
    return this.props.render(this.state); 
  }
}

<Mouse
  render={(mouse) => (
    <p>The mouse position is {mouse.x}, {mouse.y}</p>
  )}
/>

Benefits

  • Reuse code requiring similar data – Avoid duplicating container logic.
  • Decoupled implementation – How data gets used stays separate.
  • Flexible – Easily swap out rendered UI without changing containers

Use cases

  • Data subscriptions – Subscribe once, render data many ways
  • Animations – Share logic driving complex sequencing
  • Forms – Implement validation and actions only once

Tips

  • Avoid over-nesting – Clearly indicate what gets rendered
  • Check prop types – Catch errors early on invalid data
  • Optimized use – Prevent unnecessary re-renders through memoization

React Hooks

React Hooks allow you to add state and lifecycle methods to function components, avoiding the need to convert them to classes. Hooks provide similar capabilities as HOCs and render props without introducing extra nesting into your component tree.

function useMousePosition() {

  const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 })

  React.useEffect(() => {
    // Add event listeners
    // Update state
  }, []);

  return mousePosition; 
}


function App() {

  const mousePosition = useMousePosition();

  return (
    <div>
      X: {mousePosition.x}, Y: {mousePosition.y} 
    </div>
  );
}

Benefits

  • Avoid classes – Use stateful logic directly in function components
  • Flexible control flow – Call hooks conditionally or cyclically
  • Convenient component reuse – Share hook logic between components

Use cases

  • State management – Component-specific state instead of global stores
  • Data fetching – Colocate data dependencies with components
  • Event handling – Self-contained handlers keeps logic in one place

Tips

  • Call hooks unconditionally – Ensure they run in the same order
  • Lean towards built-ins – Custom hooks often indicate logic doesn’t belong
  • Destructure returned values – Avoid confusion on changes to hook APIs

Bringing it all together

While React HOCs, render props, and hooks each excel in particular use cases, they can also be combined for some extremely powerful React application architectures.

For example, hooks can be an ideal solution for encapsulating individual logic units, HOCs allow you to augment component functionalities, and render props enable flexible rendering. Together, they provide a breadth of advanced component patterns for elegantly sharing capabilities between React components.

Reach out to the experts

If diving into the intricacies of crafting sophisticated React applications with cutting-edge component functionalities sparks your interest, feel free to reach out to me today. As an independent software developer boasting over a decade of hands-on experience in JavaScript and React, I thrive on employing techniques similar to the ones discussed here.

I’m eager to discuss your project requirements, explore the possibilities, and demonstrate the caliber of solutions I can deliver. Don’t hesitate to get in touch now, and let’s kick off the conversation