Context & Architecture 🧱
Structure is everything: context shares data, composition keeps components flexible, and smart state placement avoids prop spaghetti.
1) Context API Basics ⚛️
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext({ theme: "light", setTheme: () => {} });
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const value = { theme, setTheme };
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
}
function ThemeButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
Theme: {theme}
</button>
);
}- Create a context with default values for tooling friendliness.
- Wrap subtree with a Provider to make data accessible.
- Use custom hooks (
function useTheme() { return useContext(ThemeContext); }) for a nicer API.
2) Avoiding Unnecessary Re-renders 🔄
- Context updates trigger every consumer to re-render; split providers to isolate change.
- Example: separate
ThemeContext(rare changes) fromNotificationsContext(frequent changes) to prevent thrashing. - Use selectors (or libraries like
use-context-selector) when large objects change frequently.
3) Component Composition Patterns 🧩
- Container + Presentational: containers fetch data, pass into dumb components.
- Slot-based composition: accept render props or
childrento customize layout.
function Modal({ title, actions, children }) {
return (
<section className="modal">
<header>{title}</header>
<main>{children}</main>
<footer>{actions}</footer>
</section>
);
}
<Modal title="Delete" actions={<DangerButtons />}>Are you sure?</Modal>- Prefer composition over inheritance; build small primitives that can be arranged flexibly.
4) Lifting State vs Prop Drilling vs Context 🧠
| Scenario | Strategy |
|---|---|
| Sibling components need same state | Lift to nearest common parent |
| Many levels need the same prop | Consider context |
| Only a few props pass down | Prop drilling is fine (less complexity) |
Decision framework:
- Start by lifting state to the smallest common ancestor.
- If the prop travels through many layers unchanged, introduce context.
- Keep contexts focused (auth, theme, data) to avoid monolith providers.
Key Takeaways ✅
- Context shares data globally but can trigger broad re-renders; split providers to minimize blasts.
- Composition patterns (slots, container-presentational) keep components versatile.
- Choose the simplest strategy: lift state first, add context when prop drilling becomes painful.
Recap 🔄
Use context to pass shared data, but respect its cost by scoping providers and splitting concerns. Compose components like LEGO with slots and render props, and decide between lifting state, prop drilling, or context based on how widely data must travel.
Last updated on