Managing state with React Context 
Tags: react, webdev, codenewbie, javascript
Published: 2020-10-14 06:34:21

  In my previous post I was writing about using [Redux with React](https://dev.to/olenadrugalya/react-with-redux-easy-explianlikeim5-28h4) for the state management. This blog posts is describing the different approach - using Context object.

#1. Managing state

 Let's first define what is it even means - **managing state**.

React is a framework which uses `components` as its building blocks. Components have some data which would be changed in application by the user or by event or other actions - this data is `state`. 

  React component either can have a state (its called `state-full`) or doesn't have state (its called `state-less`). 

State-full component can pass its `state` to other components (from top to bottom) and state-less component can receive the `state` via props. The ways of passing and receiving state is **state management**.

#2. Ways of state management

  If the application is small and simple, it would hardly need state management. It will probably have one main component which will manage the state for other components. 

But when application become larger, certain types of props (e.g. locale preference, UI theme) that are required by many components within an application, should be passed down from top to bottom through the components which doesn't even need them.
 
  For example, consider a *Page component* that passes a `user` and `avatarSize` prop several levels down so that deeply nested *Link* and *Avatar* components can read it:
![Props_drilling](https://dev-to-uploads.s3.amazonaws.com/i/wv1se94ea5bvoqwnlt1l.png)

Its clear from the example that only *Avatar* component needs `user` and `avatarSize` and its very annoying that:
- you have to pass those through intermediate components
- whenever *Avatar* needs any additional data, it should be passed again through many levels.....pffffttt.

  There are several ways to avoid passing props through intermediate levels (so-called "props drilling"):
- using component composition (this is in case you want to avoid passing only few props through many levels)
- using Redux library
- using Context API
- using useContext hook (in functional components)

This article is about Context API, so let's start understanding what it is.

#CONTEXT API#

**Context** gives us a possibility to pass data through the component tree without having to pass props down manually at every level. The data which is shared by the **Context**, could be called "global" for the whole application.
 
  BUT, same as with **Redux**, it doesn't mean that you have to use **Context** all the time. Note, that it is primarily used when some data needs to be accessible by *many components* at different nesting levels.

## 1. Create Context

We create our **Context** object by calling React.createContext():
![Create_Context](https://dev-to-uploads.s3.amazonaws.com/i/bz4pdr6sj6q15xxvvo64.png)

We can initialise **Context** with default values or leave it empty:
![Init_Context](https://dev-to-uploads.s3.amazonaws.com/i/j9v77c0zyd682fr1olkk.png)


## 2. Create Context Provider

Every **Context** object comes with a **Provider** React component that allows consuming components to subscribe to context changes. 

It provides a `value` prop which will be passed to the components who will need access to **Context** and state. If the value is not provided, then default value of **Context** will be used.

Once we've created **Context**, we can import it and create the component, which will initialise the state and provide MyContext further: 
![Context_Provider](https://dev-to-uploads.s3.amazonaws.com/i/fvf7nh46cmzm0yy61e65.png)

## 3. Using Context Provider
To make **Provider** accessible to other components, we need to wrap our main application with it or the parts of application, which will be using context. 

In the example below notice, that we render *PersonList* in App, which will render *Person* component and we don't provide anything to it:
![Using_provider](https://dev-to-uploads.s3.amazonaws.com/i/qouu3fqvggamjtcb89ll.png)


## 4. Create Context Consumer
This is React component that subscribes to **Context** changes.
It requires a function as a child. The function receives the current **Context** value and returns a React node. The `value` argument passed to the function will be equal to the `value` prop of the closest Provider for this **Context**. If there is no Provider for this **Context** above, the `value` argument will be equal to the `defaultValue` that was passed to `createContext()`. 

In our example application, we create a Person component, which we wrap into **Consumer** component and afterwards we can use **Context** ONLY in this particular component. 

We use **Context** the same way we would use props. It holds all the values we’ve shared in MyProducer.

![Context_consumer](https://dev-to-uploads.s3.amazonaws.com/i/thr5beq83cn00obs01dq.png)

The benefit of use of **Context** becomes clear when we look into PersonList. We don't pass any props or methods to it. We passed state directly from top parent component (App) to the component which need this state (Persons_A). In this way PersonList is simplified:

![person_list](https://dev-to-uploads.s3.amazonaws.com/i/2nliw4jte1mfpfwgcq1d.png)

# Conclusion
**Context API** gives you possibility to have a central store which can be accessed from any component. It also solves the problem with [props drilling](https://kentcdodds.com/blog/prop-drilling). If you ave been using [Redux] (https://dev.to/olenadrugalya/react-with-redux-easy-explianlikeim5-28h4) only for the purposes mentioned above, you can go ahead and replace it with **Context**. The use of third-party library in this case is obsolete. 

###Things to remember:

1. You shouldn't be reaching for context to solve every state sharing problem that crosses your desk.
2. Context does NOT have to be global to the whole app, but can be applied to one part of your tree
3. You can have multiple logically separated contexts in your app.
  

If you like to read my blog, you can [buy me coffee!](https://ko-fi.com/olenadrugalya) :)