Spaces:
Running
Running
File size: 1,729 Bytes
394073d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import { useState, useEffect } from 'react'
import { useDebouncedValue } from '@mantine/hooks'
import axios from 'axios'
export const useGeocoding = (query) => {
const [locations, setLocations] = useState([]);
const [isQueryLoading, setIsQueryLoading] = useState(false);
const [debouncedQuery] = useDebouncedValue(query, 400);
useEffect(() => {
if (!debouncedQuery || debouncedQuery.length < 3) {
setIsQueryLoading(false);
return;
}
const source = axios.CancelToken.source();
const fetchLocations = async () => {
setIsQueryLoading(true);
try {
const response = await axios.get('https://geocoding-api.open-meteo.com/v1/search', {
params: {
name: debouncedQuery,
count: 5,
language: 'en',
format: 'json'
},
cancelToken: source.token
});
const results = response.data.results || [];
const formattedLocations = results.map(item => ({
value: [item.name, item.admin1, item.country].filter(Boolean).join(', '),
lat: item.latitude,
lng: item.longitude,
}));
const uniqueLocations = formattedLocations.filter((v, i, a) =>
a.findIndex(t => t.value === v.value) === i
);
setLocations(uniqueLocations);
} catch (error) {
if (!axios.isCancel(error)) {
console.error('Geocoding error: ', error);
}
} finally {
setIsQueryLoading(false);
}
}
fetchLocations().catch(console.error);
return () => {
source.cancel('Operation canceled by the user.');
};
}, [debouncedQuery]);
return { locations, isQueryLoading, setLocations };
}
|