Global Data Sharing with React Context
Published: 2022-10-16 05:30:34

So you've learned that data passing is one way which is from parent to child components but there comes time when you  pass data too deep in React component tree. For instance, Component J needs to access state data in Component A in React component tree, to do that you might pass down that state from Components A-I finally to Component J but this causes a problem if removed any one of the Components in the up component tree, we then need to reconfigure component tree again. And here React Context comes to the rescue. React Context makes state data or any data global to the component tree that it wraps. Imagine JavaScript file with global variable, regardless how many deeply nested function is it can still access it. So in today' post I'm going to teach you how to setup React context with simple example and from there you can use it in your applications whether they're simple or complex.

# 1. Create a folder and install react
```js
// type following commands in CLI
mkdir react-context
cd react-context
npm create-react-app client
cd client
code .
npm start
```
# 2. Create the folder structure and context file
All the contexts live in context folder so that's why I created this folder. 
```js
src/
   context/
      ThemeContext.js
   App.js
   index.js
```

# 3. Open ThemeContext file and paste the following code
```js
import React, { useState } from "react";

/**
1. We create context with React.createContext({defaultValue})
2. We store created context in the variable
3. We export the context so that any component in component tree that context wraps can access it's data by the context variable
*/
export const ThemeContext = React.createContext({ themeMode: "light" });

const ThemeContextProvider = ({ children }) => {
  const [themeMode, setThemeMode] = useState("light");
  const toggleThemeMode = () => {
    if (themeMode === "light") {
      setThemeMode("dark");
    } else {
      setThemeMode("light");
    }
  };
/**

1. Context has Provider also Consumer but here it Provides data in the value attribute to component tree that it wraps.
2. Here we are sharing toggleTheemMode function that changes themeMode state from light to dark and vice versa. And themeMode with component tree
3. Children that Context wraps is component tree that ThemeContextProvider wraps and makes toggleThemeMode and themeMode available to them
*/
  return (
    <ThemeContext.Provider value={{ toggleThemeMode, themeMode }}>
      {children}
    </ThemeContext.Provider>
  );
};

export default ThemeContextProvider;

```

# 4. Open index.js and paste the following code
```js
import React from "react";
import ReactDOM from "react-dom/client";
import ThemeContextProvider from "./ThemeContext";
import "./index.css";
import App from "./App";
/**
1. We've imported ThemeContextProvider function from ThemeContext
2. In here we're wrapping App root component and which is assigned to children prop and passed as argument to ThemeContextProvider function 
3. As App is the root component, all the components regardless of the the level they are in the component tree, they can access the data ThemeContextProvider is providing
*/
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <ThemeContextProvider>
    <App />
  </ThemeContextProvider>
);

```

# 5. Open App file and paste the following code
```js
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";

const App = () => {
  const { themeMode, toggleThemeMode } = useContext(ThemeContext);

/**
1. We've imported the context ThemeContext that we'r created which makes global data available to use
2. We've also imported useContext hook to which we pass ThemeContext context and it returns use data that we've provided in that ThemeContext.Provider' value attribute
3. We've destructured themeMode and toggleThemeMode properties to use in this component
4. Based on themeMode value we're changing the background theme of the app
5. When button is clicked, we're calling toggleThemeMode which changes themeMode to light to dark or vice versa
*/
  return (
    <div
      style={
        themeMode === "light"
          ? { background: "#fff", height: "100vh" }
          : { background: "#000", color: "#fff", height: "100vh" }
      }
    >
      <button onClick={toggleThemeMode}>
        {themeMode === "light" ? "Dark Mode" : "Light Mode"}
      </button>
    </div>
  );
};

export default App;
```