Création d'un hook Reactive UsePosition () pour obtenir et suivre les coordonnées du navigateur

image


Si brièvement


Dans cet article, nous allons créer un usePosition() réactif usePosition() pour suivre la géolocalisation du navigateur. Sous le capot, ce hook utilisera les getCurrentPosition() et watchPosition() de l'objet navigateur natif navigator.geolocation . J'ai publié la version finale du hook sur GitHub et NPM .


Pourquoi créer un usePosition() en principe


L'un des avantages importants des hooks dans React est la possibilité d'isoler des fragments de code logiquement liés en un seul endroit (dans le hook), tout en évitant d'avoir à mélanger des fragments de code logiquement indépendants, par exemple, dans la méthode componentDidMount() du composant.


Supposons que nous voulons obtenir les coordonnées du navigateur ( latitude et longitude ) et après avoir reçu les coordonnées, demander des prévisions météorologiques ou la température actuelle dans cette région à un service tiers. Le code de ces deux fonctionnalités (obtention de coordonnées et demande de température) dans React est souvent placé dans une méthode componentDidMount() . Dans ce cas, la méthode componentWillUnmount() est généralement "nettoyée" par elle-même, appelant la méthode clearWatch () pour arrêter la surveillance de l'emplacement du navigateur. Une telle approche augmente la taille des méthodes, divise les sections de code connectées logiquement en parties (abonnement et désabonnement séparés de la surveillance de l'emplacement du navigateur) et combine les parties du code logiquement faiblement connectées en une seule méthode (obtention des coordonnées et de la température). La lecture du code est difficile, tout comme le débogage et le support.


Ensuite, nous essaierons de transférer la fonctionnalité associée à l'obtention des coordonnées du navigateur dans un crochet usePosition() distinct pour éviter les difficultés répertoriées ci-dessus.


Comment allons-nous utiliser le crochet usePosition()


Allons «de l'opposé» et avant d'implémenter le hook lui-même, planifions comment nous allons l'utiliser. Cela nous aidera à déterminer l'interface de raccordement (ce qu'elle acceptera et ce qu'elle retournera).


L'exemple le plus simple pour obtenir des coordonnées et les afficher à l'écran pourrait ressembler à ceci:


 import React from 'react'; //    . import { usePosition } from './usePosition'; export const UsePositionDemo = () => { //    ( ) . const { latitude, longitude, error } = usePosition(); //       (   ). return ( <> latitude: {latitude}, longitude: {longitude}, error: {error} </> ); }; 

Une seule ligne avec le crochet usePosition() et nous pouvons fonctionner avec les coordonnées de latitude et de longitude . Nous n'avons même pas utilisé explicitement les crochets useState() ou useEffect() ici. Un abonnement aux coordonnées de suivi, ainsi que la suppression d'un abonné, sont encapsulés dans un crochet usePosition() . De plus, la magie de redessiner les composants React fera tout pour nous. Au début, les coordonnées seront null ou undefined . Dès réception des coordonnées, le composant sera redessiné et nous les verrons à l'écran.


usePosition()


Notre usePosition() est une fonction JavaScript standard qui ressemble à ceci:


 //  . export const usePosition = () => { //    . } 

Nous utiliserons les crochets useState () pour le stockage interne des coordonnées et useEffect () pour vous abonner et vous désabonner des coordonnées de suivi. Pour ce faire, nous devons les importer.


 import { useState, useEffect } from 'react'; export const usePosition = () => { //     . } 

Nous allons créer des variables d'état dans lesquelles nous allons stocker des coordonnées ou une erreur dans l'obtention des coordonnées (par exemple, si l'utilisateur refuse de partager son emplacement).


 import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null); //  ... } 

À ce stade également, nous pouvons renvoyer les variables attendues du hook. Jusqu'à présent, il n'y a rien d'utile dans ces variables, mais nous le corrigerons bientôt.


 import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null); // other code goes here... return { ...position, error }; } 

Et maintenant, le moment clé de la mise en œuvre est d'obtenir des coordonnées.


 import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null); //     ,    .. useEffect(() => { const geo = navigator.geolocation; if (!geo) { setError('   '); return; } //     . watcher = geo.watchPosition(onChange, onError); //  ,       //    ,    . return () => geo.clearWatch(watcher); }, []); return {...position, error}; } 

Dans le useEffect() , nous vérifions d'abord si le navigateur prend en charge la fonctionnalité de détection de coordonnées. Si la fonctionnalité n'est pas prise en charge, nous quittons le crochet avec une erreur. Sinon, nous souscrivons à la modification de la géolocalisation du navigateur à l'aide des onError() et onError() (nous ajouterons leur code ci-dessous). Notez qu'à partir du useEffect() , nous retournons une fonction anonyme qui sera exécutée si le composant est supprimé de l'affichage. Dans cette fonction anonyme, nous nous désabonnons de la surveillance afin de ne pas obstruer la mémoire. Ainsi, toute la logique d'abonnement et de désabonnement du suivi est dans un crochet usePosition() .


Ajoutons les rappels manquants:


 import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null); const onChange = ({latitude, longitude}) => { //        position,   //    ,    . setPosition({latitude, longitude}); }; const onError = (error) => { setError(error.message); }; useEffect(() => { const geo = navigator.geolocation; if (!geo) { setError('   '); return; } //     . watcher = geo.watchPosition(onChange, onError); //  ,       //    ,    . return () => geo.clearWatch(watcher); }, []); return {...position, error}; } 

Le crochet usePosition() est prêt à l'emploi.


En fin de compte


Vous pouvez trouver une démonstration du hook et de son implémentation plus détaillée avec la possibilité de définir des paramètres de suivi sur GitHub .


J'espère que cet article vous a été utile. Codage réussi!

Source: https://habr.com/ru/post/fr458614/


All Articles