Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Comment React propage les valeurs dans l'arbre de composants sans prop drilling.
L'API Context vous permet de partager des données dans l'arbre de composants sans passer des props à chaque niveau (prop drilling). Un composant Provider enveloppe un sous-arbre et fournit une valeur. N'importe quel composant descendant peut accéder à cette valeur avec useContext — et se re-rendra automatiquement lorsque la valeur change.
React.createContext(defaultValue) crée un objet Context avec un Provider et un Consumer. La defaultValue est utilisée lorsqu'un composant consomme un contexte sans Provider correspondant au-dessus de lui dans l'arbre.
Le composant Provider accepte une prop value. Tous les composants du sous-arbre peuvent accéder à cette valeur. Vous pouvez imbriquer plusieurs Providers du même contexte — l'ancêtre Provider le plus proche l'emporte.
useContext(MonContext) retourne la valeur courante du contexte depuis le Provider le plus proche au-dessus du composant appelant. Il abonne le composant aux changements du contexte.
Lorsque la prop value du Provider change (par référence), React re-rend TOUS les composants qui appellent useContext(MonContext) dans le sous-arbre — peu importe si leur valeur consommée a réellement changé.
C'est l'efficacité clé : les composants intermédiaires qui n'appellent pas useContext ne sont pas re-rendus. Le contexte les contourne. Seuls les vrais consommateurs sont re-rendus.
Crée un objet de contexte. Prend une valeur par défaut utilisée lorsqu'aucun Provider n'est au-dessus du consommateur dans l'arbre.
Diffuse une valeur à tous les consommateurs descendants. Les Providers imbriqués remplacent les externes. La valeur doit être mémoïsée pour éviter les re-rendus inutiles.
Hook qui abonne un composant à un contexte. Se re-rend chaque fois que la valeur du contexte change.
Le contexte va directement aux consommateurs — les composants intermédiaires ne se re-rendent pas s'ils n'appellent pas aussi useContext.
React compare les valeurs de contexte avec Object.is(). Passer un nouvel objet littéral '{''}' à chaque rendu déclenche le re-rendu de tous les consommateurs même si le contenu est identique.
1const ThemeContext = React.createContext('light'); // default23// Provider — wrap at the top level4function App() {5 const [theme, setTheme] = useState('dark');67 // ⚠️ Memoize the value to avoid re-rendering all consumers8 // on every App render, even when theme hasn't changed9 const value = useMemo(() => ({ theme, setTheme }), [theme]);1011 return (12 <ThemeContext.Provider value={value}>13 <Layout />14 </ThemeContext.Provider>15 );16}1718// Consumer — anywhere in the subtree19function Button() {20 const { theme } = useContext(ThemeContext);21 return <button className={theme}>Click</button>;22}
Le contexte résout le prop drilling — passer des props à travers de nombreuses couches de composants juste pour transmettre des données à un enfant profondément imbriqué. Mais le contexte est mieux adapté aux données vraiment globales ou largement partagées (authentification, thème, locale). Pour les valeurs qui changent fréquemment, préférez Zustand ou Redux pour éviter de re-rendre chaque consommateur à chaque changement.
Your app has a global theme context providing colors, fonts, and dark/light mode. After adding it, every keystroke in a form input re-renders the entire app because the ThemeProvider is at the root.
The context value is `{ theme, toggleTheme }`. If the ThemeProvider's parent re-renders for ANY reason (new route, state change), a new object is created → all consumers re-render. With 50+ themed components, every parent re-render triggers 50+ unnecessary re-renders.
Split into two contexts: `ThemeValueContext` (read-only, changes only on toggle) and `ThemeDispatchContext` (stable setter function). Components that only READ the theme subscribe to ThemeValueContext. Components that only TOGGLE subscribe to ThemeDispatchContext. Memoize both values with useMemo.
Takeaway: Split contexts by update frequency: separate rarely-changing data (theme colors) from frequently-changing data (user input). This prevents the 'context-triggers-everything' problem and is the pattern used by Redux, Zustand, and Jotai internally.
A settings page passes `locale`, `currency`, and `dateFormat` through 6 levels of nesting: Settings → Layout → Panel → Section → Field → Label. Adding a new preference requires editing 6 components.
Prop drilling creates tight coupling — every intermediate component must know about and forward props it doesn't use. Adding, renaming, or removing a preference requires changing every component in the chain. The intermediate components also re-render when props change even though they don't USE the data.
Create a `PreferencesContext` and consume it directly in Label with `useContext(PreferencesContext)`. Intermediate components (Layout, Panel, Section, Field) don't receive or forward preference props. The preferences data 'teleports' from Provider to consumer, skipping all intermediate components.
Takeaway: Context eliminates prop drilling for cross-cutting concerns (theme, auth, locale, feature flags). Use it when data needs to be available deep in the tree and passing it through 3+ levels of components that don't use it. For frequently-updating state, consider a state manager instead.