React Context API
The React Context API provides a way in React apps to create global variables that can be passed around in the entire app and is an alternative to 'prop drilling'. Context API allows us to define several stores that are not related and can be used only in places where they are required. Context is designed to share data that we consider as global information for the entire React app.
What is the Context API in React?
React follows a design that allows one-way data flow, which means child variables can not be passed to parent components. This leads to 'prop drilling', where developers need to pass the components prop down to child components that need parent props. Passing props can be difficult when we need the child component to be more than two levels down. The React Context API provides a way in React apps to create global variables that can be passed around in the entire app and is an alternative to prop drilling. Context is also a lighter and more manageable approach to state management using Redux.
In the above picture, we can see to pass the data to child components the value must be passed to each component between the Container component and the child component. Context API helps prevent this repeated work and provides context to all the children of the main container component.
When to Use Context API?
Context is designed to share data that we consider as global information for the entire React app. The information can be about the currently authenticated user and user preferences such as theme or language. For example, consider the following code:
Here, to pass the user-preferred theme to Button, we must drill props down to two components to provide the theme information to the Button HTML element. The other way to achieve the same result is by using React Context API, as we will see in the article.
Context API in React
The first step is to create a context object. React provides a method to create a Context object, which is:
React reads the current context value from the closest matching Provider above in the tree when React renders a component subscribing to the context object that we created, myContext. The defaultValue is used only when React does not find any matching Provider in the tree. Default values for the context help for testing components in isolation.
Note: Using undefined as a Provider value does not cause the components from using default values.
Every context object comes with a Provider React component that enables React components to subscribe to context changes.
The provider component accepts the value prop that is passed to the consuming components, which are descendants of the provider component. A provider can be connected to several consumers. Providers can be used deeper within the tree to override the values.
All the consumers that are descendants of our Provider component re-renders whenever the value props of the Provider component are changed. The propagation is not subjected to the React method shouldComponentUpdate, and the consumers are updated even when the parent or ancestor component skips changing to the change in the Providers value prop. The changes between the old and new values of the prop are compared using the same algorithm used in the function Object.is.
The context created using React.createContext() can take a class's contextType property. The property lets us consume the nearest current value of the Context using this.context. This can be used in any lifecycles method, including the render functions.
Context consumer is a React component that subscribes to context changes. The function requires a child function that receives the current context value and returns a node. The argument passed to the function value is equal to the value prop of the closest Provider for the context present above in the tree.
How does the Context API Work?
The React.createContext() method returns two things that are a consumer and the provider. The Provider, as its name suggests, is a component that provides the state to its children, holds the "store", and is the parent of all the components that might need the store's value. The consumer, on the other hand, is a component that uses or consumes the state object.
What Problems Does React Context Solve?
The biggest problem that reacts context hook helps us with is the problem of pop drilling. The data flow in React is from top to bottom; that is, the content flows from parent to child component. Prop drilling is coined to describe when we pass the props down multiple levels in a nested component through components that do not require the prop.
The React context helps bypass this problem entirely, which helps to avoid the issue of prop drilling.
Will the React Context API Replace Redux?
The short answer to the question is No; it does not replace Redux entirely. Redux came as such a great and perfect solution to solve the issue of state management in React that now it is, to some extent, essential to know Redux to be called a "true" React developer. Though context API provides some benefits that Redux can't, these are:
- Simplicity: While redux can be a great tool to manage states, it causes two problems: a. Redux requires a lot of boilerplate code to start managing states in the app. b. One advantage of React one-way data binding is that this approach makes the code easy to understand. Redux takes away this easy-to-read code from the application.
- Context API allows us to define several stores that are not related and can be used only in places where they are required.
What is useContext Hook?
Creating a set of global values that can be accessed from any component was made possible in React with the introduction of the useContext hook that became first available in React 16.8. We can pass the entire object to the React.useContext() method to consume the context at the top of the component. Let us see an example to see how we use the hook.
Here, we can see the useContext hook enables us to consume the value of a context inside all the components that are children of the Provider component. The benefit of the useContext hook is that it makes our components concise and allows us to create our custom hooks.
Let us finally see an example to understand what we learned in the article.
In the above example, you will notice that though we are not passing the value of the user state through components two, three, and four, we can still access its value in the fifth component.
To use the Context in the child components, we are required to access the context values using the hook useContext. But first, we created a context UserDetailContext using the hook createContext, and wrapped the child components in the Context Provider, and supplied the state value in the value prop.
This allows all the components in the tree to have access to the user context.
- React follows a design that allows one-way data flow, which means child variables can not be passed to parent components. This leads to "prop drilling", where developers need to pass the components prop down to child components that need parent props.
- The React Context API provides a way in React apps to create global variables that can be passed around in the entire app.
- Context is designed to share data that we consider as global information for the entire React app.
- The React.createContext() method returns two things that are a consumer and the provider.
- The Provider is a component that provides the state to its children, holds the "store", and is the parent of all the components that might need the store's value.
- The consumer is a component that uses or consumes the state object.