Context API in React

#day8learningReact

Context API in React

Photo by Andrew Neel on Unsplash

Introduction:

Context is used to pass the data to another component where ever its value is required. Usually, props are used to pass values but the propagation becomes a tedious task. A value needs to propagate all through the component tree structure to make it available for a certain component.

Here In the above example if a value needs to be passed to component-4 the props need to be passed from components 1 to 2 then 2 to 3 finally to the 4th component. This method is called Prop drilling and is considered a bad practice.

An easier and optimized approach to this problem is using the Context API where the data is made globally available and sharing it with other components is easier. In the above example, the state value can now be declared in a context. This context is now made available to other components so that they can both read the value as well as modify the content. If any of the components modify the content of that state variable the other components reading that value also get rerendered and the updated value is available for them to use. This makes state management easier.

For the context values to be accessible by the components one needs to wrap those components in the context provider.

Using Context API:

Let us understand context API usage with an example of a counter. By using a counter component multiple times in another component let us try to modify the count of a counter using context instead of props.

  1. Create a component counter.

     import React from "react";
     export const Counter=()=>
     {    return(
             <div>
                 <button>INCR</button>
                 <button>DECR</button>
             </div>
     )};
    
  2. Import counter component in App.js

     import Counter from './components/counter';
     import './App.css';
    
     function App() {
       return (
         <div className="App">
           <h1>Count is 0</h1>
           <Counter/>
           <Counter/>
           <Counter/>
           <Counter/>
         </div>
       );
     }
     export default App;
    
  3. Create a context.jsx within the context folder in src. Create a context variable 'CounterContext' and a context provider 'CounterProvider'.

     import { createContext } from "react";
    
     export const CounterContext = createContext(null);
     export const CounterProvider= (props)=>{
         return(
             <CounterContext.Provider>
                 {props.childern}
             </CounterContext.Provider>
         );
     };
    
  4. In the index.jsx file import context provider and call </App> component within the context provider.

    ```typescript import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import CounterProvider from './context/Counter';

const root = ReactDOM.createRoot(document.getElementById('root')); root.render( );


5. Create a state by importing useState hook in context.jsx which holds the actual count value which is accessible by all the components wrapped in the context provider.

    ```typescript
    import { createContext, useState} from "react";

    export const CounterContext = createContext(null);
    export const CounterProvider= (props)=>{
        const [count,setCount] = useState(0);
        return(
            <CounterContext.Provider value={{count,setCount}}>
                {props.childern}
            </CounterContext.Provider>
        );
    };

the count is passed in the value which is available for all the wrapped components.

  1. Now use this value in app.js after Importing the react hook 'useContext' also import the counterContext from counter.jsx.

    
     import { useContext } from 'react';
     import './App.css';
     import {Counter} from './components/counter';
     import { CounterContext } from './context/context';
    
     function App() {
       const counterState = useContext(CounterContext);
       console.log("context:", counterState)
    
       return (
         <div className="App">
           <h1>Count is {counterState.count}</h1>
           <Counter />
           <Counter/>
           <Counter/>
           <Counter/>
         </div>
       );
     }
     export default App;
    

    Here, counterState holds the count value that is globally accessible by all wrapped components.

  2. To increment and decrement the count goto the counter.tsx and import useContext hook as well as the contextCounter created by us.

     import React,{useContext} from "react";
     import {CounterContext} from "../context/context"
    
     export const Counter=()=>
     {
         const counterContext = useContext(CounterContext);
         return(
             <div>
                 <button onClick={()=>counterContext.setCount(counterContext+1)}>INCR</button>
                 <button onClick={()=>counterContext.setCount(counterContext-1)}>DECR</button>
             </div>
         );
     }
    

    The counterContext is a state variable whose value is incremented or decremented based on a button click. The value is assigned using the setCount function that was passed in counterProvider in contex.jsx file.

  3. Hence, the counter values are updated on click of the buttons in the component and the components share the same value.