Context and custom hooks

Share app-wide values without passing props, and reuse logic.

Context gives a value to every component below a provider, without passing props through each level. Use it for things many parts of the app need: the signed-in user, the language or the theme.

React (JSX)
import { createContext, useContext, useState } from "react";

const LanguageContext = createContext("en");

export function App() {
  const [lang, setLang] = useState("en");
  return (
    <LanguageContext.Provider value={lang}>
      <button onClick={() => setLang(lang === "en" ? "ta" : "en")}>Switch language</button>
      <Greeting />
    </LanguageContext.Provider>
  );
}

function Greeting() {
  const lang = useContext(LanguageContext);
  return <h1>{lang === "ta" ? "வணக்கம்" : "Welcome"}</h1>;
}

Changing a context value redraws every component that reads it. Keep fast-changing data, such as text being typed, out of context.

Custom hooks

A custom hook is a function whose name starts with use and that calls other hooks. It shares logic, not state: each component that calls it gets its own copy.

React (JSX)
import { useEffect, useState } from "react";

export function useFetch(url) {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");

  useEffect(() => {
    let cancelled = false;
    setData(null);
    setError("");
    fetch(url)
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`Error ${r.status}`))))
      .then((d) => { if (!cancelled) setData(d); })
      .catch((e) => { if (!cancelled) setError(e.message); });
    return () => { cancelled = true; };
  }, [url]);

  return { data, error, loading: !data && !error };
}

export function Jobs() {
  const { data, error, loading } = useFetch("/api/jobs");
  if (loading) return <p>Loading…</p>;
  if (error) return <p>{error}</p>;
  return <ul>{data.map((j) => <li key={j.id}>{j.title}</li>)}</ul>;
}

Jobs now reads like a description of the screen, and any other page can load data the same way in one line.

← More hooks and routingCommon React mistakes →