React Context: A Comprehensive Guide - Part 4🔔🔔🔔

kietHTkietHT
5 min read

Intro to ReactJS basic - Part 1 ☘️☘️☘️
React JS Virtual DOM Explained - Part 2 🌲🌲🌲
Advance React Hooks - Part 3💯💯💯
ReactJS Explained Hooks - Part 5 ⚡️⚡️⚡️

🌐🌐🌐 The useContext hook is a powerful feature in React that allows functional components to access values from a React Context directly. This eliminates the need to pass props through every level of the component tree, making it easier to share data globally or across deeply nested components.

What is Context?

Before diving into useContext, it’s essential to understand what Context is in React. Context provides a way to share values (like global state, themes, or user information) between components without having to pass props manually at every level.

Creating Context

To use useContext, you first need to create a Context object using React.createContext(). Here's how it works:

  1. Create a Context:

     javascriptCopy codeimport React, { createContext } from 'react';
    
     const MyContext = createContext();
    
  2. Provide Context: Use the Provider component to make the context value available to child components.

     javascriptCopy code<MyContext.Provider value={/* some value */}>
       <ChildComponent />
     </MyContext.Provider>
    
  3. Consume Context: In any child component, use the useContext hook to access the context value.

     javascriptCopy codeimport React, { useContext } from 'react';
    
     function ChildComponent() {
       const contextValue = useContext(MyContext);
       return <div>{contextValue}</div>;
     }
    

How useContext Works

  • Accessing the Value: When you call useContext(MyContext), it returns the current value of the context. This value is determined by the nearest MyContext.Provider up the tree.

  • Reactivity: When the value of the context changes (due to a state update in the provider), all components that consume this context using useContext will re-render to reflect the new value.

Example of useContext

Here's a complete example demonstrating how to use useContext in a simple React application:

Step 1: Create a Context

javascriptCopy codeimport React, { createContext, useState } from 'react';

const ThemeContext = createContext();

Step 2: Create a Provider Component

javascriptCopy codefunction ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

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

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

Step 3: Use the Context in Child Components

javascriptCopy codeimport React, { useContext } from 'react';

function ThemedComponent() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}>
      <p>The current theme is {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}

Step 4: Wrap Your Application with the Provider

javascriptCopy codefunction App() {
  return (
    <ThemeProvider>
      <ThemedComponent />
    </ThemeProvider>
  );
}

Key Points about useContext

  1. Simplifies State Management: useContext allows you to avoid "prop drilling," where props need to be passed through many layers of components, improving the structure and readability of your code.

  2. Global State Management: It can be used to manage global states (like themes, user authentication, language settings) across the application.

  3. Reactivity: Components that use useContext will automatically re-render whenever the context value changes, keeping the UI in sync with the data.

  4. Combining with Other Hooks: useContext can be combined with other hooks like useReducer or useState for more complex state management solutions.

When to Use Context

While useContext is a powerful tool, it’s best to use it in situations where you need to share data among many components at different levels of the tree. It’s not ideal for local state management or for passing props to just a few components, as it may lead to unnecessary re-renders.

Using useContext in a React application can have implications for performance, particularly concerning re-renders. Here’s a breakdown of how useContext affects performance, along with best practices to mitigate potential issues.

How useContext Can Impact Performance

  1. Re-rendering of Consumer Components:

    • When the value provided by a Context.Provider changes, all components that consume that context using useContext will re-render. This can lead to performance bottlenecks if the context value is updated frequently or if many components are subscribed to the same context.
  2. Unnecessary Re-renders:

    • If a context value changes but only some components need the new value, all consumers of that context will still re-render. This might be inefficient if those components do not rely on the updated value.
  3. Larger Component Trees:

    • In applications with deep or complex component trees, using context extensively can cause a chain reaction of re-renders that affect performance, particularly if the updates are not optimized.

    • Example of Optimizing Context Usage

      Here’s a simplified example that demonstrates some of these techniques:

        javascriptCopy codeimport React, { createContext, useContext, useState, useMemo } from 'react';
      
        // Creating Context
        const ThemeContext = createContext();
      
        // Provider Component
        const ThemeProvider = ({ children }) => {
          const [theme, setTheme] = useState('light');
      
          const toggleTheme = () => {
            setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
          };
      
          // Memoize the context value
          const value = useMemo(() => ({ theme, toggleTheme }), [theme]);
      
          return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
        };
      
        // Consumer Component
        const ThemedComponent = React.memo(() => {
          const { theme, toggleTheme } = useContext(ThemeContext);
          return (
            <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}>
              <p>The current theme is {theme}</p>
              <button onClick={toggleTheme}>Toggle Theme</button>
            </div>
          );
        });
      
        // App Component
        const App = () => (
          <ThemeProvider>
            <ThemedComponent />
          </ThemeProvider>
        );
      
        export default App;
      

Summary

  • useContext provides a way to access the value of a context directly in functional components.

  • It simplifies state management and helps avoid prop drilling.

  • It automatically triggers re-renders in consuming components when the context value changes.

  • It’s best used for global state or shared data across many components.

0
Subscribe to my newsletter

Read articles from kietHT directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

kietHT
kietHT

I am a developer who is highly interested in TypeScript. My tech stack has been full-stack TS such as Angular, React with TypeScript and NodeJS.