Context
Definition
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
When to Use Context
When props need to be shared with most of a tree of components.
Function Component Example
Passing Props
const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee",
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222",
  },
};
function App() {
  const [themeName, setThemeName] = React.useState("light");
  const currentTheme = themes[themeName];
  return (
    <>
      <select
        onChange={(event) => setThemeName(event.target.value)}
        value={themeName}
      >
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
      <Toolbar theme={currentTheme} />
    </>
  );
}
function Toolbar({ theme }) {
  return (
    <div>
      <ThemedButton theme={theme} />
    </div>
  );
}
function ThemedButton({ theme }) {
  const { background, foreground } = theme;
  return (
    <button
      style={{
        backgroundColor: background,
        color: foreground,
      }}
    >
      Click Me
    </button>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
Using the Context API
const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee",
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222",
  },
};
const ThemeContext = React.createContext(themes.light);
function App() {
  const [themeName, setThemeName] = React.useState("light");
  const currentTheme = themes[themeName];
  return (
    <>
      <select
        onChange={(event) => setThemeName(event.target.value)}
        value={themeName}
      >
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
      <ThemeContext.Provider value={currentTheme}>
        <Toolbar />
      </ThemeContext.Provider>
    </>
  );
}
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}
function ThemedButton() {
  const { background, foreground } = React.useContext(ThemeContext);
  return (
    <button
      style={{
        backgroundColor: background,
        color: foreground,
      }}
    >
      Click Me
    </button>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
Class Component Example
In the example below, the theme is a prop to all components in the tree.
Passing Props
const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee",
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222",
  },
};
class App extends React.Component {
  render() {
    return <Toolbar theme={themes.light} />;
  }
}
function Toolbar(props) {
  // The Toolbar component must take an extra "theme" prop
  // and pass it to the ThemedButton. This can become painful
  // if every single button in the app needs to know the theme
  // because it would have to be passed through all components.
  return (
    <div>
      <ThemedButton theme={props.theme} />
    </div>
  );
}
class ThemedButton extends React.Component {
  render() {
    const { background, foreground } = this.props.theme;
    return (
      <button
        style={{
          backgroundColor: background,
          color: foreground,
        }}
      >
        Click Me
      </button>
    );
  }
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
Using the Context API
const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee",
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222",
  },
};
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext(themes.light);
// class App extends React.Component {
//   render() {
//     return <Toolbar theme={themes.light} />;
//   }
// }
class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value={themes.dark}>
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}
// function Toolbar(props) {
//   return (
//     <div>
//       <ThemedButton theme={props.theme} />
//     </div>
//   );
// }
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}
class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  render() {
    const { background, foreground } = this.context;
    return (
      <button
        style={{
          backgroundColor: background,
          color: foreground,
        }}
      >
        Click Me
      </button>
    );
  }
}
// ThemedButton.contextType = ThemeContext;
ReactDOM.createRoot(document.getElementById("root")).render(<App />);