React Hooks: useCallack Explained

·

4 min read

React Hooks: useCallack Explained

Introduction

In React, passing data from a parent component to a deeply nested child component can become cumbersome and lead to code that is hard to maintain and understand. As we have to pass data from every level, this is called prop drilling.

The useContext solves this problem. It simplifies the process of sharing data across different components without the need for prop drilling. It enables us to pass data to any nested child component without passing through every level.

In this article, we will see how to create context and use the context value in the child components.

Using the useContext hook

There are three steps we need to follow to use it.

  1. Creating the context:

    In the first step, we import the createConext() function from React. It is used to create a context instance.

     import { useContext } from 'react';
     // create a context instance
     export const MyContext = useContext('some default value');
    
  2. Passing the context value:

    In the second step, we pass the data to child components.

    The MyContext instance that we created in the first step has a MyContext.Provider component that is used to pass the data to child components.

     import { createContext } from "react";
    
     // create context instance
     export const MyContext = createContext("some default value");
    
     const App = () => {
       const data = "Hello world";
    
       return (
            // passing down the data value
            <MyContext.Provider value={data}>
    
               // components that want to consume data...
    
            </MyContext.Provider>
        );
     };
    
     export default App;
    

In this example, MyContext.Provider component accepts a value prop, which is used to pass the data to child components.

All the components that want to consume the data should be wrapped with the MyComponent.Provider component.

  1. Consuming the data in child components:

    To consume the data value in child components, we first need to import the context instance that we created in the first step and the useContext hook from React.

     import { useContext } from 'react';
    

Then we pass the context instance to the useContext hook, which returns the data that we passed to the value props of the MyComponent.Provider component.

import { useContext } from 'react';

const MyChildComponent = () =>{
   const data = useContext(MyContext);

   return <p> {data} </p>
}

In this example, we pass the MyContext instance to the useContext hook which returns the data value.

The useContext hook automatically re-renders the component when the data value changes.

Use cases

Let's consider an example where we want to implement the theming feature in our app.

  1. Define the theme context:

     //App.js
     import React, { createContext } from 'react';
     // create an instanc of context
     export const ThemeContext = createContext();
    
  2. Wrap our components with ThemeContext.Provider component:

     // App.js
     import React, { createContext } from 'react';
     export const ThemeContext = createContext();
    
     function App() {
       return (
         // Wrapping components with ThemeContext.Provider
         <ThemeContext.Provider>
            <MyComponent />
           {/* Other application components */}
         </ThemeContext.Provider>
       );
     }
    
     export default App;
    
  3. Passing down the theme data to components:

     // App.js
     import React, { createContext, useState } from 'react';
     export const ThemeContext = createContext();
    
     // Wrap components with ThemeContext.Provider
     function App() {
         const [theme, setTheme] = useState('light');
         const toggleTheme = () => {
           setTheme( prevTheme => {
               if(prevTheme === 'light') return 'dark';
               else return 'light';    
            });
       };
    
       return (
         // passing down theme data to components
         <ThemeContext.Provider value={{ theme, toggleTheme }}>
            <MyComponent />
           {/* Other application components */}
         </ThemeContext.Provider>
       );
     }
    

    In this example, we are passing down a data object with two properties: theme and toggleTheme.

    Any child component can access that object and can access the current theme value, and can also toggle that using toggleTheme method.

  4. Consuming the Theme context value:

     // App.js
     import React, { createContext } from 'react';
     export const ThemeContext = createContext();
    
     // Wrap components with ThemeContext.Provider
     function App() {
         const [theme, setTheme] = useState('light');
         const toggleTheme = () => {
           setTheme( prevTheme => {
               if(prevTheme === 'light') return 'dark';
               else return 'light';    
            });
       };
    
       return (
         // Wrapping components with Cotext provider & passing data
         <ThemeContext.Provider value={{ theme, toggleTheme }}>
            <MyComponent />
           {/* Other application components */}
         </ThemeContext.Provider>
       );
     }
    
     // Consume theme context value
     function MyComponent() {
       const { theme, toggleTheme } = useContext(ThemeContext);
    
       return (
         <div>
           <button onClick={toggleTheme}>Toggle Theme</button>
           <p>Current Theme: {theme}</p>
         </div>
       );
     }
    

    In this example, MyComponent consumes the theme data using the useContext hook. The useContext takes ThemeContext as an argument and returns the theme data that we passed in the ThemeContext.Provider component.

Conclusion

In this article, we covered the basic concepts of the useContext hook and how it can be used to share data across components without the need for prop drilling.


References

https://react.dev/reference/react/useContext