use() with Context : Conditional Context Reads in React 19
Read context with the new use() hook, even inside conditions and loops.
useContext has one rule that has bitten me plenty: it must be called unconditionally, at the top level. React 19’s use() relaxes that. You pass it the context object itself, and it works inside conditions and loops.
The top-level read
With useContext, the theme gets read before any branching, and providers use the .Provider syntax:
import { createContext, useContext } from "react";
const ThemeContext = createContext(null);
function Button({ show, children }) {
const theme = useContext(ThemeContext); // must be top-level
if (!show) return null;
return <button className={"button-" + theme}>{children}</button>;
}
function App() {
return (
<div>
<h1>Use Hook with Context</h1>
<ThemeContext.Provider value="dark">
<Button show={true}>Sign up</Button>
<Button show={false}>Log in</Button>
</ThemeContext.Provider>
</div>
);
}
export default App;
That comment is the whole problem. The read runs even when show is false and the button never renders.
Read it inside the branch
use() puts the read where the value is actually needed:
import { createContext, use } from "react";
const ThemeContext = createContext(null);
function Button({ show, children }) {
if (show) {
const theme = use(ThemeContext);
const className = "button-" + theme;
return <button className={className}>{children}</button>;
}
return null;
}
function App() {
return (
<div>
<h1>Use Hook with Context</h1>
<ThemeContext.Provider value="dark">
<Button show={true}>Sign up</Button>
<Button show={false}>Log in</Button>
</ThemeContext.Provider>
</div>
);
}
export default App;
use(ThemeContext) only runs in the branch that renders. On the providing side, you can provide with the context object directly: <ThemeContext value="...">.
Keep the context values themselves stable rather than recreating the objects every render. I put theme and locale in coarser contexts and keep dynamic data in finer ones. And check that your tooling and runtime support React 19’s use() before you commit to it.