React
  • Introduction
  • Getting Started
    • Introduction
    • Before you get started
  • 1. Fundamentals
    • Introduction
    • Rendering
      • JSX
      • Exercise
      • Solution
    • Components
      • Stateless
        • Exercise
        • Solution
      • Stateful
        • Exercise
        • Solution
      • Styling
        • Exercise
        • Solution
        • Using CSS Modules
    • Folder Architecture
  • 2. Intermediate
    • Lifecycle methods
    • Controlled and Uncontrolled components
    • Anti-patterns
    • Refs and the DOM
    • Lifting State Up
  • 3. Advanced Topics
    • Conventions
    • Reconciliation
    • Performance Optimizations
      • Avoiding Reconciliation
      • PureComponent
      • Avoiding inline lambdas
      • Development vs Production build
    • Context
  • 4. Advanced Patterns
    • Higher-order Components
    • Children as Function
    • Renderless Components
    • Portals
    • Error handling
  • Exercises
    • Introduction
    • 1. ProductList light
      • Step 1
      • Step 2
      • Step 3
      • Step 4
      • Extra
      • Solution
Powered by GitBook
On this page
  1. 4. Advanced Patterns

Renderless Components

Using components to deal with non-presentational concerns is an extremely powerful pattern that is often overlooked.

One example we use in Shopify is the <EventListener /> component, which is a useful component for adding event listeners on window that automatically manages adding the listeners on mount and cleaning them up on un-mount.

Its implementation looks something like this, though we’ve simplified it a little for the sake of this example:

class EventListener extends React.Component {
  static propTypes = {
    eventName: PropTypes.string,
    handler: PropTypes.func,
  };

  componentDidMount() {
    const {eventName, handler} = this.props;
    window.addEventListener(eventName, handler);
  }

  componentWillUnmount() {
    const {eventName, handler} = this.props;
    window.removeEventListener(eventName, handler);
  }

  render() {
    return null;
  }
}
PreviousChildren as FunctionNextPortals

Last updated 6 years ago