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:
- Fluxible adds
getStore
andexecuteAction
to component context - React-router adds an
router
object to the context for routing - react-intl adds
messages
,formats
objects andlocales
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.
[…] my last post, I talked about what context is in react, how it works and how it is used in libraries and how it […]