Learn Context in React in simple steps

Learn Context in React in simple steps

Hey coders, in this blog we are going to discuss how to use context in React for passing data between components

First, we have to understand how we can share data between different components without using Context, we can do it using Props and we are going to learn when to use Props and when to use Context for data(state, functions, etc.) sharing.

Suppose we have a simple state in our App.jsx file that is responsible for changing the theme(either the dark theme or light theme) of an App based on when a user clicks on a button that is in the Navbar of our app, Now the problem is that our state is in the App.jsx and button which changes the state is in Navbar how can we get the data(in this case setState) in the Navbar to change the theme on user click, there are 2 solutions to this problem either we can move the state into Navbar or we can pass it using props

We can follow the first step also but let us assume that we want to keep the state in the App.jsx file only

First, let's see the code of the App.jsx

import React,{useState} from 'react';
import Navbar from '../Navbar';
import MainSection from '../MainSection';
import Footer from '../Footer'

const App = () => {
    const [theme,setTheme] = useState(false);
    return(
        <div style={{backgroundColor : theme ? '#7f7f7f' : '#ffffff'}}>
        <Navbar setTheme={setTheme}/>
        <MainSection />
        <Footer />
        </div>
    )
} 

export default App

In this App.jsx we have set up the state theme using useState and set its default value to false and pass the setTheme function to Navbar using props

Now let's see the Navbar how can we use the passed data in this component to change the theme when the user clicks on the button

import React from 'react';

const Navbar = (props) => {
    return(
        <div>
            <ul>
            <li>Home</li>
            <li>About</li>
            <li>Services</li>        
            </ul>
        <button onClick={() => props.setTheme(prevTheme => !prevTheme)}>               </button>
         </div>
        )
}

So this is a simple way of managing state and passing data using props

Now let's see when we can pass data using props and we should not

Suppose there is some state in the App.jsx and we want to use it in the first child of the first parent then how can we do it we have to pass data in the form of props to the grandparent and then the parent and then to the child which finally use it. But it's not the optimized or a good solution for a more complex React application as the grandparent and parent component are not using the passed data still they are accepting it via props which are rendered each time the state changes this problem of passing props between different components is called props drilling.

What happens if we have some state in the third grandparent and we want to use it in the child of the first grandparent we cannot pass it using props as they are not hierarchically related to each other in this case what we can do is move the state to App.jsx and then pass it using props to the respected components which are not we required every time we used it.

To solve all these problems, React introduced the concept of Context

Context API is a (kind of) new feature added in version 16.3 of React that allows one to share state across the entire app (or part of it) lightly and with ease.

React context API: How it works?

First, we have to create the context using React.createContext() . It returns a consumer and a provider. The provider is a component that as its names suggests provides the data to its children.Consumer as it so happens is a component that consumes and uses the state.

Now understand how to use it.

import React, { createContext } from "react";
const UserContext = createContext();

const ContextProvider = ({ children }) => {
  const [theme, setTheme] = useState("light");
  function toggleTheme(){
     setTheme(prevState => (prevState === "light" ? "dark" : "light"))
  }
  return (
    <UserContext.Provider value={{ theme,toggleTheme }}>
      {children}
    </UserContext.Provider>
  );
};

export {ContextProvider, UserContext};

In the above example, we first create a context using createContext and then provide the value we need to provide to other components in UserContext.Provider and export the Context and ContextProvider component

It is necessary to wrap the main.jsx (in vite ) or App.jsx component with ContextProvider so the Context can pass the data or states to other components.

import React from 'react';
import App from "./App"
import ReactDOM from "react-dom";
import {ContextProvider} from "./Context"

ReactDOM.render(
    <ContextProvider>
        <App />
    </ContextProvider>, 
    document.getElementById("root")
)

Now we can consume the data in any component using useContext Hook

import React, {useContext} from "react"
import {UserContext} from "./Context"

function Header(props) {
    const {theme,toggleTheme} = useContext(UserContext) // we destructure it to get theme and toggleTheme passed using Context Provider in value 
    return (
        <header>
            <h2>{theme === "light" ? "Light": "Dark"} Theme</h2>
            <button onClick={toggleTheme}>Set Theme</button>
        </header>
    )    
}

export default Header

Now we can pass data using Context from Producer to Consumer even if they are not in hierarchy order and directly from Provider to Consumer this solves the problem of Props drilling and also our data can be managed in only one content normally in the context file. This provides a cleaner way of maintaining code and implementing the DRY (Don't Repeat Yourself ) in our code.

You can read more about the Context at https://reactjs.org/docs/context.html

That's the end of the blog, If u like and learned something from it give it a like do follow me, and Share this with your colleagues

Social Media Links https://linkfree.eddiehub.io/uddinArsalan

Follow me on Twitter,Twitter ID: https://twitter.com/home