useInsertionEffect
useInsertionEffect
est une version de useEffect
qui est déclenchée avant que React ne mette à jour le DOM.
useInsertionEffect(setup, dependencies?)
Référence
useInsertionEffect(setup, dependencies?)
Appelez useInsertionEffect
pour insérer des styles avant toute modification du DOM :
import { useInsertionEffect } from 'react';
// Dans votre bibliothèque de CSS-en-JS
function useCSS(rule) {
useInsertionEffect(() => {
// ... injectez des balises <style> ici ...
});
return rule;
}
Voir d’autres exemples ci-dessous.
Paramètres
-
setup
: la fonction contenant la logique de votre Effet. Votre fonction de mise en place peut par ailleurs renvoyer une fonction de nettoyage. Quand votre composant sera ajouté au DOM, React exécutera votre fonction de mise en place. Après chaque nouveau rendu dont les dépendances ont changé, React commencera par exécuter votre fonction de nettoyage (si vous en avez fourni une) avec les anciennes valeurs, puis exécutera votre fonction de mise en place avec les nouvelles valeurs. Une fois votre composant retiré du DOM, React exécutera votre fonction de nettoyage une dernière fois. -
dependencies
optionnelles : la liste des valeurs réactives référencées par le code desetup
. Les valeurs réactives comprennent les props, les variables d’état et toutes les variables et fonctions déclarées localement dans le corps de votre composant. Si votre linter est configuré pour React, il vérifiera que chaque valeur réactive concernée est bien spécifiée comme dépendance. La liste des dépendances doit avoir un nombre constant d’éléments et utiliser un littéral défini à la volée, du genre[dep1, dep2, dep3]
. React comparera chaque dépendance à sa valeur précédente au moyen de la comparaisonObject.is
. Si vous omettez cet argument, votre Effet sera re-exécuté après chaque rendu du composant.
Valeur renvoyée
useInsertionEffect
renvoie undefined
.
Limitations
- Les Effets ne sont exécutés que côté client. Ils sont ignorés lors du rendu côté serveur.
- Vous ne pouvez pas mettre à jour l’état au sein de
useInsertionEffect
. - Au moment où
useInsertionEffect
est exécuté, les refs ne sont pas encore associées, et le DOM n’est pas encore mis à jour.
Utilisation
Injecter des styles dynamiques depuis des bibliothèques de CSS-en-JS
D’habitude, vous styleriez vos composants React avec du CSS normal.
// Dans votre fichier JS :
<button className="success" />
// Dans votre fichier CSS :
.success { color: green; }
Certaines équipes préfèrent gérer les styles directement dans le code JavaScript, plutôt que de recourir à des fichiers CSS. Ça nécessite habituellement une bibliothèque de CSS-en-JS ou un outil. On recense trois approches fréquentes pour du CSS-en-JS :
- L’extraction statique de fichiers CSS par un compilateur
- Les styles en ligne, par exemple
<div style={{ opacity: 1 }}>
- L’injection à l’exécution de balises
<style>
Si vous utilisez du CSS-en-JS, nous vous recommandons de combiner les deux premières approches (les fichiers CSS pour les styles statiques, et les styles en ligne pour les styles dynamiques). Nous ne recommandons pas l’injection à l’exécution de balise <style>
pour deux raisons :
- L’injection à l’exécution force le navigateur à recalculer les styles beaucoup plus souvent.
- L’injection à l’exécution peut être très lente si elle survient au mauvais moment du cycle de vie de React.
Le premier problème est incontournable, mais useInsertionEffect
vous aide à résoudre le second.
Appelez useInsertionEffect
pour insérer des styles avant que le DOM soit mis à jour :
// Dans votre bibliothèque de CSS-en-JS
let isInserted = new Set();
function useCSS(rule) {
useInsertionEffect(() => {
// Comme expliqué plus haut, nous ne recommandons pas l'injection à l'exécution de balise <style>.
// Mais si vous devez absolument le faire, alors il est important de le faire dans un
// useInsertionEffect.
if (!isInserted.has(rule)) {
isInserted.add(rule);
document.head.appendChild(getStyleForRule(rule));
}
});
return rule;
}
function Button() {
const className = useCSS('...');
return <div className={className} />;
}
Tout comme useEffect
, useInsertionEffect
est ignoré côté serveur. Si vous avez besoin de collecter les règles CSS utilisées côté serveur, vous pouvez le faire durant le rendu :
let collectedRulesSet = new Set();
function useCSS(rule) {
if (typeof window === 'undefined') {
collectedRulesSet.add(rule);
}
useInsertionEffect(() => {
// ...
});
return rule;
}
En détail
Si vous insérez des styles pendant le rendu et que React traite une mise à jour non bloquante, le navigateur recalculera les styles à chaque étape du rendu de l’arborescence de composants, ce qui peut être extrêmement lent.
useInsertionEffect
est préférable à l’insertion de styles dans useLayoutEffect
ou useEffect
parce qu’il garantit qu’au moment de l’exécution des autres Effets de vos composants, les balises <style>
auront déjà été insérées. Faute de ça, les calculs de mise en page au sein d’Effets classiques seraient erronés en raison de styles obsolètes.