Criando um gancho UsePosition () reativo para obter e rastrear coordenadas do navegador

imagem


Se brevemente


Neste artigo, criaremos um gancho reativo usePosition() para rastrear a localização geográfica do navegador. Sob o capô, esse gancho usará os métodos getCurrentPosition() e watchPosition() do objeto nativo do navegador navigator.geolocation . Publiquei a versão final do gancho no GitHub e NPM .


Por que criar um gancho usePosition() em princípio


Uma das vantagens importantes dos ganchos no React é a capacidade de isolar fragmentos de código relacionados logicamente em um local (no gancho), evitando a necessidade de misturar fragmentos de código não relacionados logicamente, por exemplo, no método componentDidMount() do componente.


Suponha que desejemos obter as coordenadas do navegador ( latitude e longitude ) e, após receber as coordenadas, solicite uma previsão do tempo ou a temperatura atual nessa região a um serviço de terceiros. O código dessas duas funcionalidades (obtenção de coordenadas e solicitação de temperatura) no React é geralmente colocado dentro de um método componentDidMount() . Nesse caso, o método componentWillUnmount() geralmente é "limpo" por si só, chamando o método clearWatch () para parar de monitorar o local do navegador. Essa abordagem aumenta o tamanho dos métodos, divide seções de código logicamente conectadas em partes (assinando e cancelando separadamente a monitoração do local do navegador) e combina partes do código logicamente fracamente conectadas em um método (obtenção de coordenadas e temperatura). A leitura do código é difícil, assim como a depuração e o suporte.


Em seguida, tentaremos transferir a funcionalidade associada à obtenção das coordenadas do navegador em um gancho usePosition() separado para evitar as dificuldades listadas acima.


Como vamos usar o gancho usePosition()


Vamos "do oposto" e antes de implementar o gancho em si, vamos planejar como o usaremos. Isso nos ajudará a determinar a interface do gancho (o que ele aceitará e o que retornar).


O exemplo mais simples de obter coordenadas e exibi-las na tela pode ser assim:


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

Apenas uma linha com o gancho usePosition() e podemos operar com coordenadas de latitude e longitude . Nem usamos os useState() ou useEffect() explicitamente aqui. Uma assinatura para rastrear coordenadas, assim como excluir um assinante, é encapsulada em um gancho usePosition() . Além disso, a mágica de redesenhar os componentes do React fará tudo por nós. No início, as coordenadas serão null ou undefined . Assim que as coordenadas forem recebidas, o componente será redesenhado e as veremos na tela.


Implementação de usePosition()


Nosso gancho usePosition() é uma função JavaScript comum que se parece com isso:


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

Usaremos os ganchos useState () para armazenamento interno de coordenadas e useEffect () para assinar e cancelar a assinatura das coordenadas de rastreamento. Para fazer isso, precisamos importá-los.


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

Criaremos variáveis ​​de estado nas quais armazenaremos coordenadas ou um erro na obtenção de coordenadas (por exemplo, se o usuário se recusar a compartilhar sua localização).


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

Também nesta fase, podemos retornar as variáveis ​​que são esperadas do gancho. Até o momento, não há nada útil nessas variáveis, mas iremos corrigi-lo em breve.


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

E agora o momento chave da implementação é obter coordenadas.


 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}; } 

No gancho useEffect() , primeiro verificamos se o navegador suporta a funcionalidade de detecção de coordenadas. Se a funcionalidade não for suportada, sairemos do gancho com um erro. Caso contrário, assinaremos a alteração da localização geográfica do navegador usando os onError() onChange onChange() e onError() (adicionaremos o código abaixo). Observe que do gancho useEffect() , retornamos uma função anônima que será executada se o componente for removido da exibição. Nesta função anônima, estamos cancelando a assinatura da vigilância para não entupir a memória. Portanto, toda a lógica de assinar e cancelar a assinatura do rastreamento está em um gancho usePosition() .


Vamos adicionar os retornos de chamada ausentes:


 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}; } 

O gancho usePosition() está pronto para uso.


No final


Você pode encontrar uma demonstração do gancho e sua implementação mais detalhada com a capacidade de definir parâmetros de rastreamento no GitHub .


Espero que este artigo tenha sido útil para você. Codificação bem sucedida!

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


All Articles