@eggtronic/react-weather-widget
Version:
A nice weather widget component for react
70 lines (63 loc) • 2.26 kB
text/typescript
import useAsync from './useAsync';
import useGeoLocation from './useGeoLocation';
import { OpenWeatherMapExclude, WeatherData } from '../types/weatherWidget';
import { BASE_API_URL } from '../utils/index';
/**
*
* @param key api key from openweathermap
* @param units
* For temperature in Fahrenheit, use units=imperial
* For temperature in Celsius, use units=metric
* Kelvin is used by default, so there is no need to use the units parameter in the API call if you want this
* @param exclude https://openweathermap.org/api/one-call-api
*/
export default function useFetchWeather(
key: string,
units?: string,
exclude?: OpenWeatherMapExclude,
geo?: {
lat: string,
lon: string
} | undefined
) {
const { latitude, longitude, loading, error, shouldDetectLocation } = useGeoLocation(!!geo);
const state = useAsync(async () => {
if (loading) return { loading: true };
if (error) return { error, loading: false };
const url = `${BASE_API_URL}` +
`lat=${geo?.lat || latitude}` +
`&lon=${geo?.lon || longitude}` +
`${units ? `&units=${units}` : ''}` +
`${exclude ? `&exclude=${exclude.join(',')}` : ''}` +
`&appid=${key}`;
const response = await fetch(url);
const result = await response.json();
return result;
}, [latitude, longitude, loading, error]);
const errorMsg: string | undefined
= state.value?.error?.message
|| state.error?.message;
/** there is a hack to check if it is currently loading geo or weather data
* if loading is true then geo is loading.
* if geo loaded, and if there is no error and no timezone
* then weather is loading.
*/
let loadingMsg: string | null = null;
if (shouldDetectLocation) {
if (loading) {
loadingMsg = 'Geo Locating ...';
} else if (!state.value.timezone && !errorMsg) {
loadingMsg = 'Fetching Weather Data ...';
}
}
if (!shouldDetectLocation) {
if (state.loading && !errorMsg) {
loadingMsg = 'Fetching Weather Data ...';
}
}
const weatherData: WeatherData | null
= state.value
? state.value
: null;
return [errorMsg, loadingMsg, weatherData];
}