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({
      increment: this.increment,

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

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.


Safer, saner JavaScript.

Read all

Let’s keep in touch

Reach out on Twitter or subscribe for (very) occasional updates.

Hey, I'm RJ: digital entomologist and intermittent micropoet, writing from the beautiful Rose City.