{{announcement.body}}
{{announcement.title}}

React.js Context Tutorial: A Better Way to Store State?

DZone 's Guide to

React.js Context Tutorial: A Better Way to Store State?

We look in to the JavaScript code necessary to allow your React.js application to store state within the Context layer of its architecture.

· Web Dev Zone ·
Free Resource

While creating a component in a typical React app, we end up creating layers of functional components and class components. Much of the time, we end up following a pattern where we pass props to a functional or class component from Grand Parents to Great Grand Children (referring to the hierarchy shown below). There are cases when props are not required at a certain level but are there just to be passed to another component.

Image title

We can use React's context pattern to solve this problem. It's based on the Consumer Provider pattern, i.e. a producer stores the state and methods to manipulate the state and the consumer can access them whenever necessary. 

Image title

Demo: Create a React app with create-react-app and remove the boilerplate code.

Now use the ceateContext as shown below (I've named this file provider.js ):

import React from 'react'

export const Context = React.createContext();
class ContextProvider extends React.Component {

state={digit:2}

    render() {
        return (<Context.Provider value={{digit:this.state.digit}} >
            {this.props.children}
        </Context.Provider>)
    }
}
export default ContextProvider

Here we created a Context that is provided by the React.createContext API. We then sore thestate at this level, and provide its schemas as  {digit:2}. Then we simply return Context.Provider with props as the value.

Now we modify the index.js file by wrapping the App component in the <Context.Provider> component.

ReactDOM.render(
<ContextProvider>
   <App />
</ContextProvider> , document.getElementById('root'));

Now it is possible to access the state maintained by Context at any level inside the App component without passing it down.

I created a GreatGrandChildren.js file that looks like the below code block:

import React from 'react'
import { Context } from './ContextProvider'
export const GreatGrandChildren = () => {
    return (<React.Fragment>
        <br></br>
        <Context.Consumer>
            {(context) => <span>   GreatGrandChildren {context.digit}</span>}
        </Context.Consumer>

    </React.Fragment>)
}

Here we need to import the Context that we created and render our component as a function inside <Context.Consumer>.

We can now access Context values inside the Consumer at any level. This saves us from performing prop chaining.

Now, if we want to update the state, add a handler method in context, and make it so it can be accessed by the consumer to handle the state value, we need to modify the context provider's code to add the handler.

 return (<Context.Provider value={{ digit: this.state.digit, onDigitChange: () =>
         this.setState({ digit: this.state.digit + 1 })
          }} >

 And we can access this handler from the consumer by doing the following:

 <Context.Consumer>
            {(context) => <span>   GreatGrandChildren {context.digit}  <button onClick={context.onDigitChange}>increase digit</button></span>}
 </Context.Consumer>

Get the code on GitHub.



If you enjoyed this article and want to learn more about React, check out this collection of tutorials and articles on all things React.

Topics:
web dev ,react.js tutorial ,javascript state ,javascript tutorial ,context

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}