49

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

 5 years ago
source link: https://www.tuicool.com/articles/hit/nqEZZz7
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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.

fei6RvY.png!web

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. 

fqieUbm.png!web

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 the state 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 .


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK