Hi,
I am having an issue with my React-Native weather application and fetching weather data from openweathermap.org.
I have two react hooks in my application:
- The first hook gets the coordinates of the device’s current position (useGeolocation).
- The second hook makes a fetch request to OpenWeatherMap for the current weather data (useFetch).
My useGeolocation hook works fine and retrieves the current position and returns a latitude and longitude. I then use these coordinates in my API request when calling my useFetch hook so that I have an accurate location when retrieving the weather.
The problem lies within my useFetch hook. I am passing a url parameter to my hook and using an async/wait arrow function within a useEffect hook to fetch the data from the API.
However, once the hook has been called and the fetch request is made. The response returns the following:
LOG weather data {“cod”: “400”, “message”: “wrong latitude”}
LOG weather data {“cod”: “400”, “message”: “wrong longitude”}
Then a third response returns a portion of the data with the following :
Actual response
"base": "stations",
"main": {
"temp": 282.55,
"feels_like": 281.86,
"temp_min": 280.37,
"temp_max": 284.26,
"pressure": 1023,
"humidity": 100
},
"visibility": 16093,
"wind": {
"speed": 1.5,
"deg": 350
},
"clouds": {
"all": 1
},
"dt": 1560350645,
"sys": {
"type": 1,
"id": 5122,
"message": 0.0139,
"country": "US",
"sunrise": 1560343627,
"sunset": 1560396563
},
"timezone": -25200,
"id": 420006353,
"name": "Mountain View",
"cod": 200
}
Instead of the following:
Expected response
{
"coord": {
"lon": -122.08,
"lat": 37.39
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 282.55,
"feels_like": 281.86,
"temp_min": 280.37,
"temp_max": 284.26,
"pressure": 1023,
"humidity": 100
},
"visibility": 16093,
"wind": {
"speed": 1.5,
"deg": 350
},
"clouds": {
"all": 1
},
"dt": 1560350645,
"sys": {
"type": 1,
"id": 5122,
"message": 0.0139,
"country": "US",
"sunrise": 1560343627,
"sunset": 1560396563
},
"timezone": -25200,
"id": 420006353,
"name": "Mountain View",
"cod": 200
}
I would like to be able to return the expected response and fetch this data on the first request. Comparing the two sets of data, it seems I am missing the coords object and the weather array at the very top of the expected response.
Please find two files below my functional component and my usefetch hook:
WeatherContainer.js
const WeatherContainer = () => {
const {latitude, longitude, status} = useGeolocation();
const apiURL = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${globalVariables.API_KEY}`;
const {result, isLoading, error} = useFetch(apiURL);
return (
<View style={styles.container}>
<View style={styles.innerContainer}>
<Text>{latitude}</Text>
<Text>{longitude}</Text>
<Text>{roundTemp(result.main.temp - globalVariables.KELVIN)}</Text>
</View>
</View>
);
};
export default WeatherContainer;
useGeolocation.js
useGeolocation.js
const useGeolocation = () => {
const [latitude, setLatitude] = useState(null);
const [longitude, setLongitude] = useState(null);
const [status, setStatus] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const getLocation = async () => {
const androidGranted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (androidGranted == PermissionsAndroid.RESULTS.GRANTED) {
setStatus('User accepted geolocation services');
Geolocation.getCurrentPosition(
position => {
setLatitude(position.coords.latitude);
setLongitude(position.coords.longitude);
console.log(position);
},
error => {
console.log(error.code, error.message);
setError(error.message);
},
{enableHighAccuracy: true, timeout: 15000, maximumAge: 10000},
);
} else if (Platform.OS === 'ios') {
setStatus('User accepted geolocation services');
Geolocation.requestAuthorization();
} else {
setStatus('User denied geolocation services');
}
};
getLocation();
}, []);
return {latitude, longitude, status, error};
};
useFetch.js
const useFetch = url => {
const [result, setResult] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const getData = async () => {
setIsLoading(true);
try {
await fetch(url)
.then(res => res.json())
.then(json => {
setResult(json);
console.log(json);
});
} catch (error) {
console.log('Error from fetch: ', error);
setError(error);
} finally {
setIsLoading(false);
}
};
getData();
}, [url]);
return {result, isLoading, error};
};
export default useFetch;
Note: All imports are included within my editor. However, if I need to include these then I will on request.
Thank you for taking the time to read.
Tom