React Context with TypeScript

The official Context API released with React 16.3 gives developers a new tool for sharing state across an application. If that sounds suspiciously global, rest assured: each context must be explicitly referenced by both the Provider that supplies it and the Consumer that puts its to work.

Using it with TypeScript simply means typing each Context instance:

type CounterContext = {
  count: number,
  updateCount(delta: number): void,
};

export default React.createContext<CounterContext>({
  count: 42,
  updateCount: (n) => {
    throw new Error('updateCount() not implemented');
  }
});

While TypeScript has little impact on the implementation, its compile-time guarantees mean less time spent digging into Consumer misbehavior every time a Provider supplies malformed state. That’s more time for adding value to the application, and at very little cost.

So, as long as the types check out, we’re all set to share state through our shiny new CounterContext.

import CounterContext from './context';

const Count: React.SFC<{}> = () => (
  <CounterContext.Consumer>
    {({ count, updateCount }) => (
      <div>
        <h1>Count: {count}</h1>
        <button onClick={() => updateCount(1)}>+1</button>
      </div>
    )}
  </CounterContext.Consumer>
);

class Container extends React.Component<{}, { count: number }> {
  readonly state = { count: 0 };

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

  render() {
    return (
      <CounterContext.Provider
        value={{
          count: this.state.count,
          updateCount: this.increment,
        }}
      >
        <Count />
      </CounterContext.Provider>
    );
  }
}

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


TypeScript

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.