Using React Context with TypeScript
- 5/24/2018
- ·
- #typescript
- #howto
- #react
TypeScript takes React's Context API to the next level by safely typing shared state.
When the official Context API released with React
16.3, developers got a
powerful new container for application state. If “context” sounds suspiciously
global, rest assured: each context must be explicitly referenced by both the
Provider
that supplies it and the Consumer
that puts it to work.
Still, TypeScript is a helpful addition–a statically-verified way to ensure
that context instances returned by createContext
can only be used as intended.
Using a React Context with TypeScript is much like in JavaScript, but with an
both Provider
and Consumer
restricted to whatever type is assigned to the
original createContext
call. Here’s a simple example showing a context with a
type signature, default value, and (stubbed) callback:
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.