Context composition arranges providers and consumers in the JSX tree so descendants receive the nearest available value. A consumer outside every provider receives the context's default value. section 10.1.3
Use these rules when composing context:
- Provide the same context multiple times, including nested providers, to override values for different subtrees. section 10.1.3
- Consume context with useContext in functional components; use Consumer mainly when maintaining older class-based code. section 10.1.3
- Resolve each consumer's value by looking upward through the component tree until reaching the nearest provider. section 10.1.3
Scoped button border widths
Create BorderContext with a default value of 1. Let Button read it with useContext and use the value for its border. Header buttons use the default width, while CartButton nests a provider with value 5, so its button receives the local width. section 10.1.3
Listing 10.4 Border width by context
import { useContext, createContext } from "react";
const BorderContext = createContext(1); #1
function Button({ children }) {
const borderWidth = useContext(BorderContext); #2
const style = {
border: `${borderWidth}px solid black`,
background: "transparent",
};
return <button style={style}>{children}</button>;
}
function CartButton() {
return (
<BorderContext.Provider value={5}> #3
<Button>Cart</Button>
</BorderContext.Provider>
);
}
function Header() {
const style = {
padding: "5px",
borderBottom: "1px solid black",
marginBottom: "10px",
display: "flex",
gap: "5px",
justifyContent: "flex-end",
};
return (
<header style={style}>
<Button>Clothes</Button>
<Button>Toys</Button>
<CartButton />
</header>
);
}
function Footer() {
const style = {
padding: "5px",
borderTop: "1px solid black",
marginTop: "10px",
display: "flex",
justifyContent: "space-between",
};
return (
<footer style={style}>
<Button>About</Button>
<Button>Jobs</Button>
<CartButton />
</footer>
);
}
function App() {
return (
<main>
<Header />
<h1>Welcome to the shop!</h1>
<BorderContext.Provider value={2}> #4
<Footer />
</BorderContext.Provider>
</main>
);
}
export default App;
Inspect the complete border-width example, including the context definition, consumer component, nested provider, and surrounding header and footer components. section 10.1.3
