In this post I want to explore the idea of using contexts in React to implement dependency injection (DI) in our application.
We’ll cover two things:
- What contexts are in React and how they work
- Why we care about DI and how we can implement them using contexts.
React and Contexts
Contexts were formalized in React 0.12, and are planned for React 1.0. They
are a mechanism for a component to pass properties down to their descendent components.
The difference between
context is that
context chains to descendents,
props do not.
Let’s take a look at a small example.
Parent component, we implement two things:
childContextTypesstatic property, which specifies the propeties that this component will provide to its descendent components.
getChildContext()method, which returns the concrete values for the context.
GrandChild component implements the
contextTypes static property, which
specifies what will be on its context (accessible via
This is powerful because we decoupled
GrandChild’s dependency on a user service to our
containing component (
Parent in this case).
Childcomponent does not need to chain the context down to
GrandChild. This is different from
propswhere we would need to manually chain all properties down.
Dependency injection is a pattern that implements the Inversion of Control design.
In recent years it has gained more mindshare with frontend developers due to the popularity of the AngularJS framework.
The value of DI is that we can depend on abstract ideas instead of concrete implementations. This makes our code much more testable and increases reusability – we’ll see this later.
Example: Random Number Generator
Let’s imagine a component
RandomNumber that renders a randomly generated integer between 1 and
The current implementation couples the component to two functions:
coupling makes testing impossible, and also makes it impossible to reuse if our random number provider changes.
Let’s see how the same component looks using contexts.
This makes testing very easy because we now control exactly what
to our component.
We have also increased reusability of our component by allowing late-binding of the
functions. If we wanted to provide different rounding strategies we will be able to – say rounding
to two decimal places. We can also swap out
Math.random with a better number generator if needed and
we will not need to touch
We can extend our random number generator example to all services. In the context of Flux, we can use DI for Stores and ActionCreators so that our components are completely decoupled from concrete types.
Taking It Up A Notch
With ES7 decorators, we can create even nicer abstractions for DI in React.
Let’s take a look at two decarators:
@inject- sets the
contextTypeson our component.
childContextTypeson our component and binds the context.
If we go back to our earlier
UserAvatar code, here’s how we can use the new decorators
in our application.
This is using a concept called higher-order components (HoC). Basically, we use functions (decorators) that take in a component as input and ouputs a component. This allows us to add additional behaviour or metadata to the original component.
In this post we saw how dependency injection can be achieved in React through the use of contexts.
We saw how dependency injection can make our code more testable and more reusable.
- Introduction to Contexts in React by Dave King