PC & Mobile

Comment utiliser un IntersectionObserver dans un crochet de réaction – Le développeur non traditionnel – Moyen

Comment utiliser un IntersectionObserver dans un crochet de réaction - Le développeur non traditionnel - Moyen


Photo par chuttersnap sur Unsplash

(Je voudrais donner un crédit, lorsque je pense que le crédit est dû. Les exemples de code de cet article ont été écrits par moi, mais ont été très bien informés par le code écrit par mon ancien collègue, Jared tuxsudo sur Twitter)

L'une des choses les plus difficiles à faire sur le Web consiste à déterminer si un élément est visible ou si un élément est en relation avec son élément parent. Historiquement, cela impliquait d'exécuter des calculs déclenchés par un événement de défilement, ce qui peut rapidement devenir un handicap pour la performance de votre application.

Heureusement, une méthode plus efficace et beaucoup plus performante a été introduite: l'observateur d'intersection. L'API Intersection Observer permet de vérifier de manière asynchrone le rapport entre l'intersection d'un élément et une fenêtre et ne déclenche un rappel que lorsque le ou les seuils prédéfinis sont atteints. Cela a ouvert de nombreuses expériences utilisateur difficiles à mettre en œuvre de manière performante, telles que le défilement infini, les images à chargement paresseux ou le retard des animations jusqu'à ce qu'elles soient visibles.

Récemment, je voulais explorer la manière de procéder pour mettre cela en œuvre dans un crochet de réaction. J'ai rencontré beaucoup de pièges, mais heureusement, Dan Abramov a récemment publié un guide très utile sur useEffect sur son blog, Overreacted, qui m'a énormément aidé à comprendre ces pièges et ce que je devais faire pour les réparer. J'ai donc pensé résumer ce que j'ai appris pour vous aider, espérons-le, à éviter les mêmes erreurs que celles que j'ai commises.

Comment fonctionne l'API Intersection Observer?

Afin de bien comprendre l'API Intersection Observer, je vous recommande de consulter la documentation disponible sur MDN. En un mot, vous devez créer un observateur qui «observera» un nœud DOM et appellera un rappel si un ou plusieurs des seuils sont atteints. Un seuil peut être n'importe quel rapport de 0 à 1, où 1 signifie que l'élément est 100% dans la fenêtre et 0 est 100% hors de la fenêtre. Par défaut, le seuil est défini sur 0. Voici un exemple de création d'un observateur que j'ai emprunté à MDN:

const callback = (entrées, observateur) => { 
entries.forEach (entry => {
// Chaque entrée décrit un changement d'intersection pour un observé
// élément cible:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// heure d'entrée
});
};
const observateur = new IntersectionObserver (callBack);

Vous pouvez éventuellement transmettre un objet en tant que second paramètre au constructeur IntersectionObersver. Cet objet vous permet de configurer l'observateur. Vous pouvez configurer 3 propriétés possibles: root, rootMargin et seuil.

La propriété de seuil peut être une ration unique, comme 0,2 , ou un tableau de seuils, comme [0.01, 0.02, 0.03,....]. le rootProperty est l'élément à utiliser comme fenêtre d'affichage lors du calcul du rapport d'intersection. La propriété racine doit être un ancêtre de l'élément observé et constitue la fenêtre de visualisation du navigateur par défaut. Enfin, vous pouvez définir le racine de marge property, en utilisant la syntaxe de marge CSS, pour spécifier une zone invisible autour de la racine permettant de calculer le seuil.

Donc, l'exemple ci-dessus pourrait être réécrit comme ceci:

const options = {
racine: domNode,
rootMargin: '0px',
seuil: [0.98, 0.99, 1]

}
const observateur = new IntersectionObserver (callBack, options);

Nous avons l’observateur, mais il n’observe encore rien. Pour commencer l’observation, vous devez passer un nœud dom à la observer méthode. Il peut observer un nombre illimité de nœuds, mais vous ne pouvez en passer qu'un à la fois. Lorsque vous ne voulez plus qu’il observe un nœud, vous appelez le inaperçu méthode et passez le noeud que vous souhaitez arrêter de regarder ou vous pouvez appeler le déconnecter méthode pour l'empêcher d'observer n'importe quel nœud, comme ceci:

observer.observer (nodeOne); // n'observant que nodeOne
observer.observer (nodeTwo); // observant à la fois nodeOne et nodeTwo
observer.unobserver (nodeOne); // observant uniquement nodeTwo
observer.disconnect (); // n'observe aucun noeud

Il y a plus de choses, mais cela couvre les cas d'utilisation les plus typiques d'IntersectionObserver.

Comment l'utilisez-vous dans un crochet?

Tout d’abord, nous devons pouvoir fournir l’entrée renvoyée par IntersectionObserver à partir du rappel. Pour ce faire, nous utilisons le useState crochet. Nous allons supposer que nous n'observerons qu'un nœud à la fois, nous allons donc déstructurer le tableau d'entrées dans la première entrée du tableau et l'enregistrer comme suit:

Il y a déjà un gros casse-tête avec ça. UseIntersect sera appelé à chaque fois que des composants seront rerender, ce qui signifie que l'observateur sera instancié à chaque fois avec un nouvel IntersectionObserver. Ce n'est pas le comportement prévu.

Ce que nous voulons utiliser est le useRef crochet. Le hook useRef est souvent utilisé pour garder la trace d'un nœud DOM. Vous pouvez donc effectuer des tâches impératives ultérieurement (comme le mettre en évidence), mais useRef peut être utilisé pour conserver toute valeur entre les rendus. Nous accédons à la valeur d’un arbitre à travers le actuel propriété sur le ref lui-même. La ref elle-même est modifiable et cette valeur actuelle peut être réaffectée à tout moment, mais nous obtiendrons toujours le même objet ref avec sa valeur la plus récente sur chaque rendu.

On peut se demander quelle est la différence entre useRef et useState puisque les deux renverront la valeur actuelle. La plus grande différence est la façon dont vous mettez à jour la valeur et ce que cela signifie pour le reste du composant qui l'utilise. Vous pouvez uniquement mettre à jour l'état en utilisant la deuxième valeur renvoyée par useState où la valeur de la référence peut être mise à jour à tout moment en attribuant une nouvelle valeur à la propriété actuelle. En outre, la mise à jour de la valeur d'une référence ne signalera pas une réémission, contrairement à la mise à jour de l'état.

Mettons à jour notre crochet pour utiliser useRef:

Notre crochet se rapproche, mais il nous manque encore la partie la plus importante: l'observation. Car nous avons besoin de deux choses: une référence de noeud et nous devons commencer à l'observer en utilisant le useEffect crochet. Nous pourrions essayer de l'implémenter comme ceci:

Cela a déjà beaucoup de pièges. Le premier casse-tête n’était pas évident pour moi tant que je n’en ai pas appris plus sur la useEffect crochet a travaillé. La fonction que vous revenez de la useEffect hook est exécuté lorsque le composant est en cours de démontage, ce qui vous permet de nettoyer des éléments tels que la déconnexion de l'observateur, ce que nous faisons. Le piège est que, depuis actuel peut être muté, il n’est pas sûr d’y accéder simplement à partir du actuel propriété. Si pour une raison quelconque, à l'avenir, j'ai décidé de réaffecter le actuel propriété à quelque chose d'autre, comme nul ou un autre observateur, alors la fonction de nettoyage ne peut pas réellement nettoyer comme je l’attendais. La chose à faire est d’assigner le actuel propriété à une variable dans le useEffect accrocher et ensuite utiliser la variable au lieu de la actuel propriété directement. Comme ça:

L’autre problème est que cet effet sera répété plusieurs fois car lorsque l’observateur appelle le rappel, il met à jour l’état, ce qui provoque une restitution, ce qui provoque la restitution. useEffect crochet pour être exécuté à nouveau. La première pensée serait de passer nœud dans le tableau de dépendance pour useEffect. Le problème est que passer l’arbitre a son propre "cycle de vie" et ne peut pas être fiable pour dire au useEffect crochet pour ignorer l'exécution de ce rendu.

Pour résoudre ce problème, nous devons cesser d'utiliser le useRef accrocher à la useState crochet comme ceci:

En passant le setNode fonction, nous utilisons le modèle de référence de rappel au lieu du nouveau modèle de référence (pour en savoir plus sur les différentes façons de gérer les références, vous pouvez consulter le guide du débutant pour les références dans la publication de réaction). Cela passera le noeud dans le rappel que nous fournissons, ce qui dans notre cas mettra à jour l'état pour qu'il soit le nouveau noeud. Cela signifie que lors du premier passage, le nœud sera nul et nous devons donc vérifier que le nœud a une valeur avant de tenter de l’observer.

Les choses vont bien, mais il y a encore deux choses à considérer. La première est la suivante: que se passe-t-il si le composant utilisant le hook change le nœud que l’observateur «observe»? Cela déclenchera un changement d'état, puisque le setRef sera appelé sur le nouveau noeud. Depuis que le noeud a changé, le useEffect s’exécutera à nouveau et commencera à observer le nouveau nœud. Ça sonne bien non? Qu'en est-il de l'ancien noeud? Vous avez raison, nous n'avons jamais cessé de l'observer. Cela signifie qu'il y aura plus d'une entrée dans le rappel et que nous pourrions enregistrer la mauvaise entrée dans l'état, sans oublier le fait que nous observons des nœuds dont nous ne nous soucions plus.

Pour résoudre ce problème, nous devons déconnecter l'observateur à chaque fois. useEffect s'appelle comme ceci:

Cela garantira que l'observateur ne regarde que le nœud qui nous intéresse. La dernière chose dont nous avons besoin est de pouvoir personnaliser notre observateur. Nous pouvons passer l'objet config dans le crochet. Nous pouvons fournir des valeurs par défaut aux options afin de sécuriser le fonctionnement de notre hook. Voici la version finale de notre crochet:

Maintenant que nous avons notre crochet personnalisé entièrement fonctionnel, voyons-le en action. J'ai créé un bac à sable en utilisant notre nouveau useIntersect crochet. Vous pouvez regarder à travers le code et voir comment cela fonctionne, mais au fond, j'ai plusieurs boîtes, toutes les autres vont disparaître ou s'agrandir, en fonction de leur taux d'intersection. Vous pouvez basculer chaque zone dans une zone de fondu ou de développement et le raccordement comptabilise correctement les modifications de nœud.

Les crochets offrent un excellent moyen de composer des fonctionnalités, comme un observateur d'intersection, dans un composant. Une fois que vous avez compris comment ça marche, vous pouvez faire des choses incroyables.

Show More

SupportIvy

SupportIvy.com : Un lieu pour partager le savoir et mieux comprendre le monde. Meilleure plate-forme de support gratuit pour vous, Documentation &Tutoriels par les experts.

Related Articles

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Close
Close