React LogouseContext and Context API

The React Context API provides a way to pass data through the component tree without having to pass props down manually at every level. This is often referred to as avoiding "prop-drilling." It's particularly useful for sharing "global" data like the current authenticated user, application theme, or preferred language that many components might need.

Core Concepts:

1. `React.createContext()`: This function creates a Context object. When React renders a component that subscribes to this Context object, it will read the current context value from the closest matching `Provider` above it in the tree.
* It takes an optional `defaultValue` argument. This value is used when a component tries to consume the context without a matching `Provider` above it, or if it has `null` as its value.

2. `Context.Provider`: Every Context object comes with a Provider React component. It allows consuming components to subscribe to context changes. The `Context.Provider` component accepts a `value` prop to be passed to consuming components that are descendants of this Provider. A Provider can be nested inside another Provider to override values deeper within the tree. All components rendered within a `Provider` will have access to its `value` prop.

3. `useContext(Context)` Hook: This is the modern and recommended way to consume context in functional components. It accepts a context object (the value returned from `React.createContext`) and returns the current context value for that context. React will automatically re-render the component if the context value changes. This hook effectively replaces the `Context.Consumer` component from class components, providing a cleaner and more direct way to access context.

How it works:

* You create a context using `createContext()`.
* You wrap the part of your component tree that needs access to this context with `Context.Provider`.
* You pass the data you want to share as the `value` prop to the `Provider`.
* Any functional component within that `Provider`'s subtree can then access that `value` using the `useContext()` hook, without receiving it as a prop.

Benefits:

* Avoids Prop Drilling: Eliminates the need to pass props down through many intermediate components that don't directly use them, making component trees cleaner and easier to manage.
* Global State Management (Simple Cases): Excellent for sharing application-wide data like theme settings, user authentication status, or preferred language, where state changes are not excessively frequent or complex.
* Cleaner Code: Reduces boilerplate associated with passing props through multiple layers.

When to use it:

* Theming: Implementing dark/light mode or different visual themes across the application.
* User Authentication: Sharing user details, authentication tokens, or login status.
* Localization: Providing language strings or regional settings to various components.
* Simple Global State: For small to medium-sized applications where dedicated state management libraries (like Redux, Zustand) might be overkill.

When NOT to use it (or consider alternatives):

* Frequent Updates: If the context value changes very frequently, components consuming it will re-render often. While React is optimized, excessive re-renders *could* lead to performance issues if not carefully managed (e.g., using `React.memo`).
* Complex Global State: For large, highly interactive applications with complex state interactions, asynchronous actions, or the need for advanced middleware, dedicated state management libraries often provide better tooling, performance optimizations, and debugging capabilities.
* Instead of Prop Drilling for a Few Levels: If you only need to pass a prop down 1-2 levels, regular prop drilling is often simpler, more explicit, and easier to trace than introducing context.

Example Code

```jsx
// App.js
import React, { createContext, useContext, useState } from 'react';
import './App.css'; // Assume App.css contains basic theme styles

// 1. Create the Context
// Define a default value for the context. This is used if a component
// tries to consume context without a Provider above it.
const ThemeContext = createContext({
  theme: 'light',
  toggleTheme: () => {},
});

// 2. Create a Provider component (optional, but good practice for encapsulation)
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  // The value prop is crucial: it holds the data that consumers will receive
  const contextValue = { theme, toggleTheme };

  return (
    <ThemeContext.Provider value={contextValue}>
      {children}
    </ThemeContext.Provider>
  );
}

// 3. Create a component that consumes the context using useContext hook
function ThemeToggleButton() {
  // useContext takes the Context object and returns its current value
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <button onClick={toggleTheme} className={`button-${theme}`}>
      Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
    </button>
  );
}

// Another component that uses the theme for styling
function ThemedParagraph() {
  const { theme } = useContext(ThemeContext);
  return (
    <p className={`paragraph-${theme}`}>
      This paragraph's style changes with the theme! Current theme: {theme}
    </p>
  );
}

// A component that might be deeply nested in the component tree
function Toolbar() {
  return (
    <div style={{ marginTop: '20px', borderTop: '1px solid #ccc', paddingTop: '10px' }}>
      <h3>Toolbar Component</h3>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const { theme } = useContext(ThemeContext); // Consume theme directly, no props needed from parent
  return (
    <button className={`button-${theme}`}>
      Toolbar Button ({theme} mode)
    </button>
  );
}

// Main App component
function App() {
  // The 'ThemeProvider' wraps the components that need access to the theme context.
  // All descendants of ThemeProvider can now use useContext(ThemeContext).
  return (
    <ThemeProvider>
      <div className="App">
        <h1>Context API Theme Example</h1>
        <ThemeToggleButton />
        <ThemedParagraph />
        <Toolbar /> {/* Toolbar could be a deeply nested component, still gets the theme */}
      </div>
    </ThemeProvider>
  );
}

export default App;

/*
  // Example App.css for context
  .App {
    font-family: sans-serif;
    padding: 20px;
    min-height: 100vh;
    transition: background-color 0.3s ease, color 0.3s ease;
  }

  .App.light {
    background-color: #f0f0f0;
    color: #333;
  }

  .App.dark {
    background-color: #333;
    color: #f0f0f0;
  }

  button {
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 5px;
  }

  .button-light {
    background-color: #007bff;
    color: white;
  }

  .button-dark {
    background-color: #6610f2;
    color: white;
  }

  .paragraph-light {
    color: #333;
  }

  .paragraph-dark {
    color: #f0f0f0;
  }
*/
```