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>
);
}
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() {} };
}
- 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
The answer
Write it yourself first. Then compare it with a reference solution and the checks it passes.
Checking your sign-in…