React Render Props with TypeScript

React render props are a useful tool for sharing logic across multiple components. Think of them as a special case of higher-order component where–instead of creating new child components–different render methods can be injected.

Suppose we have a logical component (call it CounterDataProvider) responsible for managing a count value consumed by components deeper inside the React DOM. If we want to allow different rendering strategies for the count, we can type CounterDataProvider to receive a render prop.

type CounterState = {
  count: number,
};

type ChildProps = CounterState & {
  increment(d: number): void,
};

type CounterProps = {
  render(state: ChildProps): React.ReactNode,
};

Yes, it’s exactly what it sounds like. The props we’ll pass to CounterDataProvider‘s props include a render method that takes in ChildProps and produces a ReactNode–the exact same signature we’d see in a garden-variety Stateless Functional Component (SFC). And that’s exactly what we’ll pass to render!

import * as React from 'react';

class CounterDataProvider extends React.Component<CounterProps, CounterState> {
  readonly state: CounterState = {
    count: 44,
  };

  increment = (delta: number) =>
    this.setState({ count: this.state.count + delta })

  render() {
    return this.props.render({
      ...this.state,
      increment: this.increment,
    });
  }
}

export default () => (
  <CounterDataProvider
    render={(props: ChildProps) => (
      <div>
        <h1>Count: {props.count}</h1>
        <button onClick={() => props.increment(1)}>+1</button>
        <button onClick={() => props.increment(-1)}>-1</button>
      </div>
    )}
  />
);

If we wanted to imagine a completely different UI for the counter, no problem! Just give render a different SFC and away you go.

Find a demo of it all working together in the React with TypeScript repository on Github.

Hey, I'm RJ! For more learnings about software and management, find me @rjzaworski or sign up for my semi-regular newsletter.

Let’s keep in touch

Send me timely updates on software, product, and process.