Poznajemy API, które jest w stanie pokazać nam nasze położenie geograficzne. Do dzieła.
Sposób użycia:
navigator.geolocation.getCurrentPosition(success, error, options);
Argumenty:
- success (obowiązkowe): callback, który przyjmie pozycję i wywoła się, gdy mamy sukces (po pierwsze, zezwalamy na użycie geolokacji, po drugie kod zakończył działanie)
- error (opcjonalne): callback, który ma się wykonać, gdy wystąpi jakiś błąd
- options (opcjonalne): obiekt, zawierający opcje:
- enableHighAccuracy: domyślnie false, jak true to działa wolniej i więcej energii używa, ale lepsze wyniki podaje
- timeout: ile maksymalnie ma czekać, aż zwróci wynik (w ms)
- maximumAge: domyślnie 0, też w ms, ile czasu może mieć maksymalnie zkeszowany wynik, aby można go było uznać za akceptowalny
Oto przykład użycia z MDN:
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};
function success(pos) {
const crd = pos.coords;
console.log("Your current position is:");
console.log(`Latitude : ${crd.latitude}`);
console.log(`Longitude: ${crd.longitude}`);
console.log(`More or less ${crd.accuracy} meters.`);
}
function error(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
}
navigator.geolocation.getCurrentPosition(success, error, options);
Dobra, a teraz custom hook w React useGeolocation:
import { useState } from "react";
function useGeolocation() {
const [isLoading, setIsLoading] = useState(false);
const [position, setPosition] = useState({});
const [error, setError] = useState(null);
function getPosition() {
if (!navigator.geolocation)
return setError("Your browser does not support geolocation");
setIsLoading(true);
navigator.geolocation.getCurrentPosition(
(pos) => {
setPosition({
lat: pos.coords.latitude,
lng: pos.coords.longitude
});
setIsLoading(false);
},
(error) => {
setError(error.message);
setIsLoading(false);
}
);
}
return { isLoading, position, error, getPosition };
}
Chyba proste i nie trzeba tłumaczyć. No, może ten return setError, to warto zaznaczyć – jako że return, to ustawiamy i wychodzimy, dalej kod się nie wykonuje.
Możemy jeszcze zobaczyć jak autor sobie użył tego kodu:
export default function App() {
const {
isLoading,
position: { lat, lng },
error,
getPosition
} = useGeolocation();
const [countClicks, setCountClicks] = useState(0);
function handleClick() {
setCountClicks((count) => count + 1);
getPosition();
}
return (
<div>
<button onClick={handleClick} disabled={isLoading}>
Get my position
</button>
{isLoading && <p>Loading position...</p>}
{error && <p>{error}</p>}
{!isLoading && !error && lat && lng && (
<p>
Your GPS position:{" "}
<a
target="_blank"
rel="noreferrer"
href={`https://www.openstreetmap.org/#map=16/${lat}/${lng}`}
>
{lat}, {lng}
</a>
</p>
)}
<p>You requested position {countClicks} times</p>
</div>
);
}
Mam nadzieję, że dekompozycja obiektów nas nie dziwi. Wystarczy wywołać get postion aby wszystko działo się samo, tam w mapce mamy użycie tej dekompozycji lat i lng.
Oczywiście jeżeli nie pozwolimy na geolokację, to potem musimy odświeżyć stronę, inaczej kolejne kliknięcia niewiele zmienią. Zezwolenia to jest Permissions API, zupełnie inny temat.