
Along with React 16.8 came a plethora of new features including the ability to subscribe to a central data repository or context. There are many tutorials to follow to learn how to use context, but this one sets out to make it as simple as possible. A repository exists that shows these topics in a working app.
Many of the features available now in React seem similar to features that exist in frameworks like Redux which are frequently built into React applications.
Unfortunately using a data store means that you’ll increase your code complexity slightly but it can have advantages when your application is large enough to require a central data repository for certain values.
High Level Overview
In order to use a data store we’ll need these three things.
- Context – The source where the data and its setters reside.
- Provider – The class that provides access to the context.
- Consumer – This is the class that will get access to the context.
These are the only three things that we need in order to work with contexts.
Create a Context
import React from 'react';
// First we need a new Context
export const CounterContext = React.createContext();
As you can see we can get a new context from the React
import. I’m exporting CounterContext
because I will be using it later in our counter example.
You may want to put your contexts in a central place in your application. In the demonstration repository I put my context files in src/store
.
Create a Provider
// Next we need a provider
export class CounterProvider extends Component {
state = {
counter: 0
};
render() {
return (
<CounterContext.Provider value={{
state: this.state,
addCount: () => this.setState({ counter: this.state.counter + 1 }),
subCount: () => this.setState({ counter: this.state.counter - 1 })
}}>
{this.props.children}
</CounterContext.Provider>
);
}
}
Both the context and the provider should be in the same file above but I have it separated here for clarity. Refer to the repository if you have any questions.
Our provider needs a context to provide to a consumer. The provider requires an attribute named value
that will be made available to any consumers of the context.
Fortunately value
can be anything and in the code above I have included setters that allow us to easily update our state . There are many ways to approach building applications and certain people may want to use a Store for more complicated projects but that is beyond the scope of this article.
Consume the Values
Next, let’s create our consumer. This is the Counter
component created in src/components/Counter.js
.
import React from 'react';
import {CounterContext} from '../store/simpleContext';
function Counter(){
return(
<div>
<CounterContext.Consumer>
{(context)=>(
<div>
<p>Count: {context.state.counter}</p>
<button onClick={context.addCount}>+</button>
<button onClick={context.subCount}>-</button>
</div>
)
}
</CounterContext.Consumer>
</div>
)
}
export default Counter;
As you can see getting information out of a context is a little more work than getting it from props. First we have to create a consumer from the context we just made ( using CounterContext.Consumer
. Then we need to pass the context in as a function parameter to component that will be built.
This is our consumer, but we still need to wrap this component in a provider.
In App.js
we use our counter that we made. It is here that we need to wrap Counter
in the context provider.
import React from 'react';
import {CounterProvider} from './store/simpleContext';
import Counter from './components/Counter';
function App() {
return (
<div className="App">
<CounterProvider>
<Counter/>
</CounterProvider>
</div>
);
}
export default App;
At this point you should have everything you need to get context working in React. Unfortunately using context adds more complexity to your project so it’s a design decision that must be made carefully. Having said that, it also allows for a more intuitive flow and compartmentalization of data. If you find that you’re having to pass props around in a deeply nested component tree you may want to think about using context to help you out.