You may have wondered lately what all the buzz is about Context and what it might mean for you and your React sites. Before Context, when the management of state gets complicated beyond the functionality of setState, you likely had to make use of a third party library. Thanks to recent updates by the awesome React team, we now have Context which might help with some state management issues.
What Does Context Solve?
How do you move the state from a parent component to a child component that is nested in the component tree? You know that you can use Redux to manage state, but you shouldn’t have to jump to Redux in every situation.
There’s a way to do this without Redux or any other third party state management tool. You can use props!
Say the feature you want to implement has a tree structure similar to what I have below:
The state lives in the App component and is needed in UserProfile and UserDetails components. You need to pass it via props down the tree. If the components that need this state are 10 steps deep, this can become tedious, tiring, and error prone. Each component is supposed to be like a black box — other components should not be aware of states that they do not need. Here is an example of an application that matches the scenario above.
We are passing the state from one component to another using props. The User component has no need of the state, but it has to receive it via props in order for it to get down the tree. This is exactly what we want to avoid.
This new Context is assigned to a const variable, in this case, the variable is UserContext. You can see that there is no need to install a library now that createContext() is available in React (16.3.0 and above).
The Provider component makes the context available to components that need it, which are called Subscribers. In other words, the Provider component allows Consumers to subscribe to changes in context. Remember that the context is similar to a global application state. Thus, components that are not Consumers will not be subscribed to the context.
If you are coding locally, your context file will look like this:
The Provider accepts a value prop to be passed to it Consumer components descendants. In this case, we will be passing the user state to the Consumer components. You can see that we are not passing the state to User component as props. That means we can edit the User component and exclude the props since it does not need them:
What if we want to allow users to change their first and last name? That’s also possible. Consumer components can re-render whenever there are changes to the value passed by the Provider component. Let’s see an example.
We’ll have two input fields for the first and last name in the consumer component. From the Provider component, we will have two methods that update the state of the application using the values entered in the input fields. Enough talk, let’s code!
We are passing an object which contains state and actions to the value props which the Provider receives. The actions are methods that will be triggered when an onChange event happens. The value of the event is then used to update the state. Since we want to update either the first name or last name, there’s a need to preserve the value of the other. For this, we make use of ES6 Spread Operator, which allows us to update the value of the specified key.
With the new changes, we need to update UserProfile component.
The data that will be used in the Consumer components will be done defined when we initialized a new Context.
When things get complicated, and you are tempted to run yarn install [<insert third-party library for state management], pause for a second — you’ve got React Context at the ready. Don’t you believe me? Maybe you’ll believe Kent C. Dodds.