Context
Context lets you pass data through the component tree without prop drilling.
Creating a Context
import { createContext } from "tachys"
interface Theme {
primary: string
background: string
}
const ThemeContext = createContext<Theme>({
primary: "#007bff",
background: "#ffffff",
})Providing a Value
Wrap a subtree with the Provider:
function App() {
const theme = { primary: "#e91e63", background: "#fafafa" }
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
)
}Consuming Context
Use useContext to read the current value:
import { useContext } from "tachys"
function ThemedButton() {
const theme = useContext(ThemeContext)
return (
<button style={{ backgroundColor: theme.primary, color: "#fff" }}>
Click me
</button>
)
}Or use the use() hook:
import { use } from "tachys"
function ThemedButton() {
const theme = use(ThemeContext)
// ...
}Nested Providers
Inner providers override outer ones:
<ThemeContext.Provider value={lightTheme}>
<Sidebar />
<ThemeContext.Provider value={darkTheme}>
<MainContent />
</ThemeContext.Provider>
</ThemeContext.Provider>Consumer Component
For cases where you can't use hooks (or for compatibility with libraries that use the render-prop pattern), each context also has a .Consumer component:
<ThemeContext.Consumer>
{(theme) => (
<button style={{ backgroundColor: theme.primary }}>
Themed Button
</button>
)}
</ThemeContext.Consumer>The children prop must be a function that receives the current context value and returns a VNode. The value comes from the nearest Provider ancestor, or the default value if none is found.
TIP
Prefer useContext or use() in new code. Consumer exists primarily for compatibility with third-party React libraries.
Performance
Context consumers re-render whenever the provided value changes (by reference). To avoid unnecessary re-renders:
- Memoize the value with
useMemoif it's an object:
const actions = useMemo(() => ({
toggle: (id: number) => { /* ... */ },
remove: (id: number) => { /* ... */ },
}), [])
return <ActionsCtx.Provider value={actions}>...</ActionsCtx.Provider>- Split contexts by update frequency -- put rarely-changing data (e.g., theme) in a separate context from frequently-changing data (e.g., current user input).