cf.completefrontend

Write the codeMedium

Write a ThemeProvider and a useTheme hook that throws a helpful error outside the provider

Write ThemeContext.jsx with two named exports. ThemeProvider takes children and an optional initialTheme, "light" by default, and keeps the theme in state. useTheme() returns { theme, toggleTheme } from the nearest ThemeProvider above the component; toggleTheme() switches between "light" and "dark". A provider inside another keeps a theme of its own.

Called with no ThemeProvider above, useTheme() throws an Error whose message is useTheme must be used inside a ThemeProvider, instead of quietly returning a default. And keep readers cheap: the object useTheme() returns stays the same until the theme changes, and toggleTheme is the same function on every render, so a memo component that reads the theme doesn't render when only the provider's parent does.

function ThemeLabel() {
  const { theme } = useTheme();
  return <p>Theme: {theme}</p>;
}
 
function ThemeSwitch() {
  const { toggleTheme } = useTheme();
  return <button onClick={toggleTheme}>Switch theme</button>;
}
 
function Page() {
  return (
    <ThemeProvider initialTheme="dark">
      <header><ThemeSwitch /></header>
      <main><ThemeLabel /></main>
    </ThemeProvider>
  );
}
Write this (ThemeContext.jsx)
import { createContext, useContext, useState } from "react";
 
const ThemeContext = createContext(null);
 
export function ThemeProvider({ children, initialTheme = "light" }) {
  const [theme, setTheme] = useState(initialTheme);
  // Provide the theme and a way to switch it to everything inside.
  return children;
}
 
export function useTheme() {
  // Read the nearest ThemeProvider's value.
  return { theme: "light", toggleTheme() {} };
}
The checks your code must pass
  • readers get the light theme by default
  • starts with initialTheme
  • toggleTheme switches every reader under the provider
  • useTheme throws a helpful error outside a provider
  • a provider inside another keeps its own theme
  • a memo reader doesn't render when only the provider's parent does
  • toggleTheme is the same function after the theme changes

Try it in the editor

The answer

Write it yourself first. Then compare it with a reference solution and the checks it passes.

Checking your sign-in…