Take a deeper look into context in React.js – Part 1

Recently I’ve been working with react.js, fluxible and react-router and I need some better understanding of how context works in react.js. I read a good article about the undocumented feature of react.js: context

In short, a context is an object with attributes that are implicitly passed down from an element to all of its children and grandchildren.

To share data/attributes with children components with context, a component defines the attribute names and data types available in the context by defining the attribute childContextTypes. It also need to define getChildContext method that returns the data values of attributes in the context. The keys in childContextTypes must be exactly the same set of keys in the object returned by getChildContext method.

When a child component wants to use data from parent’s context, it must first declare what it wants to use explicitly by defining the attribute contextTypes.
contextTypes is an object specifying the name and type of attributes it want to use.

Deeper look into context

Merged context

Contexts defined in ancestral components are merged for descendant components.

One very important feature that did not get mentioned in the above article is that, child components can access contexts defined by multiple components in the parent tree. For example, if both the parent component and the grandparent component have defined their own context by implementing the childContextTypes attribute and
getChildContext method, the children can access all context defined by it’s parent and grand parents. All it has to do is to declear it by contextTypes.

If the same attribute in the context is defined by both parent and grandparent, the parent will overwrite that attribute and what the child components get is the one defined by the parent component.

Here is the some example code

Contexts are immutable

Context are created at the time a component is created. React will look at what the components is asking for by inspecting the contextTypes attribute, and search the ancestors in the parent tree for matching context values. If all value with matching types are found, the contextTypes attribute is set to null, otherwise, a warning is emitted.

Modifying the context in the parent component does nothing to the children. You can modify the context in the child component. But this only affects as far as how the context is used inside the child component and there is no sensable reason to do so.

Reusable components

But why can’t we simply share whatever context object of the parent component has with all its children and grandchildren ? Why do we have to declear contextTypes in the child component to get it working ?

Components in react are supposed to be resuable. That means, a component could be rendered in different parent tree with different ansestral components that may or may not come with the required context attributes. It is important to have the context dependencies explicitly declared and provide developers with warnings if those dependencies can not be resolved when a component is put into use in a wrong context.

What should be in the context

React libraries

Let’s see how context is used in some react libraries:

  1. Fluxible adds getStore and executeAction to component context
  2. React-router adds an router object to the context for routing
  3. react-intl adds messages, formats objects and locales string|array to the context for translations and text formating

For a library, context is a good way for sharing data/functionalities in react components without polluting the application business logic.

Application

In an application, a context is a environment your react app runs. Examples are environments variables (browser, os/server environemnt etc) and features.

However, context is actually something should not be abused. Your applications should run regardless what context it is in. To keep your components pure, use props when possible.

What’s next

In my next post I am going to cover owner-based context and parent-based context. Please stay tuned.

One thought on “Take a deeper look into context in React.js – Part 1

Leave a comment