React Context: How to Use the useContext Hook

React Context: How to Use the useContext Hook

Components are the product's building blocks in React. These components are defined in a tree hierarchy, with one component being the parent of another.

In react, data flows down the hierarchy, from parent component to child component and further down. Suppose the component is far down the hierarchy from the root component. In that case, the data is routed through all of the middle components first before being made available to the component far down the hierarchy.

To avoid this type of design, some reactjs developers use redux as a library that works on the global store, storing data or state globally and making it directly accessible to all components without passing data or state down the hierarchy.

Context is yet another intriguing and amazing way introduced to react to store data or state globally.

To implement react context into your project, follow these steps:

1. Create a file to store a context object and then export that context object from that file.

import React from‘ react’
export const ThemeContext = React.createContext(‘dark’);

We've created and exported a context object here. A default parameter or value (default props) can be passed to a context object. If the parent component does not pass any props, it will use the default props defined in the context object. A provider function is always included with a react context object. We'll look at what a provider is in the next step.

2. Now in a parent component whose values are to be passed to the child component.

Any child component that descends the hierarchy will be wrapped in a react context provider.

Note: If a child component wants to access the state or value of an ancestor, the child component's parent or grandparent must be wrapped in a react context provider.

Component A —> Component B —-> Component C ——> Component D

(ancestor) (1st child) (2nd child) (3rd child)

Here Component A is the root component, component B is the child of component A, component C is the child of component B, component D is the child of component C.

If child 3 wishes to access data from the ancestor or component A, any component B, C, or D must be wrapped in provider. The child who wants to access the data, whether it is a parent or the child itself, should be wrapped in the context provider of the ancestor who passed the data.

import {
    ThemeContext,
    themes
} from './theme-context';
import ThemedButton from './themed-button'; // An intermediate component that uses the ThemedButton function Toolbar(props)
Toolbar(props) {
    return (Change Theme ThemedButton > );
}
class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            theme: themes.light,
        };
        this.toggleTheme = () => {
            this.setState(state => ({
                theme: state.theme === themes.dark ? themes.light : themes.dark,
            }));
        };
    }
    render() {// The ThemedButton button inside the ThemeProvider uses the theme from the state while the one outside uses the default dark theme
        return (Section > Page > );
    }
}
ReactDOM.render(, document.root);

The ancestor, in this case, is 'class App'. The Toolbar is a child functional component and ThemedButton is also a child component. The Toolbar is wrapped inside the context provider. The context provider sends values to Toolbar and any child components. ThemedButton is not wrapped in any of the context providers, therefore, it will take the context's default value. The value passed by the provider to the child component can be accessed by it or any child of that child component.

Note: Any child component wrapped inside the provider will use the values passed, and if the child component is not wrapped inside the provider, it will use the react context provider's default value.

Now that we've completed the parent component definition, let's move on to the child component definition.

3. We can access the values of child components in multiple ways.

Let's go over the first method for accessing the value in a child component (contextType).

import {
    ThemeContext
} from './theme-context';
class ThemedButton extends React.Component {
    render() {
        let props = this.props;
        let theme = this.props; // this.props used
       return ();
    }
}
ThemedButton.contextType = ThemeContext;
export default ThemedButton;
After Context
import {
    ThemeContext
} from './theme-context';
import React from‘ react’ class ThemedButton extends React.Component {
    render() {
        let props = this.props;
        let theme = this.context; //Replaced by this.context
        return ();
    }
}
ThemedButton.contextType = ThemeContext;
export default ThemedButton;

The child component, in this case, is ThemedButton. If you want to access the value, use contextType before exporting the component. After that, everywhere you have used this.props can be replaced by this.context.

React hooks are another method for accessing values.

import {
    ThemeContext
} from './theme-context';
import React, {
    useContext
} from‘ react’ class ThemedButton extends React.Component {
    render() {
        let theme = useContext(ThemeContext);
        return ();
    }
}
export default ThemedButton;

We used the hooks useContext in this case. Following that, we can directly access the properties shown above.