Ojasa Mirai

Ojasa Mirai

ReactJS

Loading...

Learning Level

🟢 Beginner🔵 Advanced
🌍 Context API Basics📦 Creating Context🔌 Context.Provider🔍 useContext Hook🎯 Passing Data with Context🔄 Context with useState⚡ Context Performance🏗️ Context Best Practices
Reactjs/Context/Context Usestate

🔄 Context with useState — Making Context Dynamic

Context values don't have to be static. By combining Context with `useState`, you can create dynamic values that update throughout your app.


🎯 Using useState with Context

The key is to put your state and its setter function into the Context value. Any component can then access and update that state:

import { createContext, useContext, useState } from "react";

const ThemeContext = createContext({
  isDark: false,
  toggleTheme: () => {},
});

function App() {
  const [isDark, setIsDark] = useState(false);

  const toggleTheme = () => setIsDark(!isDark);

  const value = { isDark, toggleTheme };

  return (
    <ThemeContext.Provider value={value}>
      <Header />
      <Content />
    </ThemeContext.Provider>
  );
}

function Header() {
  const { isDark, toggleTheme } = useContext(ThemeContext);

  return (
    <header style={{ background: isDark ? "#1a1a1a" : "#fff" }}>
      <button onClick={toggleTheme}>
        Switch to {isDark ? "light" : "dark"} mode
      </button>
    </header>
  );
}

When you click the button, `toggleTheme()` updates the state, and all components using this Context automatically re-render with the new value.

💡 Updating Context Values from Multiple Components

Since the state is in the Provider, multiple components can trigger updates:

import { createContext, useContext, useState } from "react";

const CounterContext = createContext({
  count: 0,
  increment: () => {},
  decrement: () => {},
});

function App() {
  const [count, setCount] = useState(0);

  const value = {
    count,
    increment: () => setCount(count + 1),
    decrement: () => setCount(count - 1),
  };

  return (
    <CounterContext.Provider value={value}>
      <Display />
      <Controls />
    </CounterContext.Provider>
  );
}

function Display() {
  const { count } = useContext(CounterContext);
  return <h1>Count: {count}</h1>;
}

function Controls() {
  const { increment, decrement } = useContext(CounterContext);

  return (
    <div>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}

Display shows the count. When Controls updates it, Display automatically updates.

<details>

<summary>📚 More Examples</summary>

// Example 1: Modal visibility context
const ModalContext = createContext({
  isOpen: false,
  openModal: () => {},
  closeModal: () => {},
});

function App() {
  const [isOpen, setIsOpen] = useState(false);

  const value = {
    isOpen,
    openModal: () => setIsOpen(true),
    closeModal: () => setIsOpen(false),
  };

  return (
    <ModalContext.Provider value={value}>
      <Main />
    </ModalContext.Provider>
  );
}

function OpenButton() {
  const { openModal } = useContext(ModalContext);
  return <button onClick={openModal}>Open Modal</button>;
}

function Modal() {
  const { isOpen, closeModal } = useContext(ModalContext);

  if (!isOpen) return null;

  return (
    <div>
      <h2>Modal Content</h2>
      <button onClick={closeModal}>Close</button>
    </div>
  );
}

// Example 2: User authentication context
const AuthContext = createContext({
  user: null as User | null,
  login: async (email: string, password: string) => {},
  logout: () => {},
});

function App() {
  const [user, setUser] = useState<User | null>(null);

  const login = async (email: string, password: string) => {
    // Call API...
    setUser({ id: "1", email, name: "Alice" });
  };

  const logout = () => {
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      <App />
    </AuthContext.Provider>
  );
}

</details>

🎨 Real-World Example: Theme Toggle with Persistence

A common pattern is persisting theme preference to localStorage:

import { createContext, useContext, useState, useEffect } from "react";

type Theme = "light" | "dark";

const ThemeContext = createContext({
  theme: "light" as Theme,
  setTheme: (theme: Theme) => {},
});

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState<Theme>(() => {
    // Load from localStorage on startup
    const saved = localStorage.getItem("theme");
    return (saved as Theme) || "light";
  });

  // Save to localStorage whenever theme changes
  useEffect(() => {
    localStorage.setItem("theme", theme);
    document.documentElement.setAttribute("data-theme", theme);
  }, [theme]);

  const value = { theme, setTheme };

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

function ThemeToggle() {
  const { theme, setTheme } = useContext(ThemeContext);

  return (
    <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
      Current: {theme}
    </button>
  );
}

function App() {
  return (
    <ThemeProvider>
      <ThemeToggle />
      <Content />
    </ThemeProvider>
  );
}

📊 State Management Patterns

PatternUse CaseExample
Single useStateOne piece of stateTheme, language
Multiple statesRelated dataUser, theme, modal
With callbacksState + actionsCount with increment
With localStoragePersistenceSaved preferences

🔑 Key Takeaways

  • ✅ Combine Context with `useState` for dynamic values
  • ✅ Include setter functions in Context value
  • ✅ Multiple components can trigger state updates
  • ✅ All consumers automatically re-render on state change
  • ✅ Use `useEffect` to sync Context with localStorage
  • ✅ Keep related state together in one useState call
  • ✅ Provide clear action functions (e.g., `toggleTheme`) not just setters

Ready to practice? Challenges | Next: Context Performance


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn