I have a working sample however I am sure it can be refactored for improvement. The project is a Weather app built with React, Node/Express and OpenWeather API. Basically the lat
and lon
values from first API response are needed as params in second API request. Reason for having Node server is to hide API key in browser. :)
Here is a breakdown of folder structure(only includes relevant files):
weather-app/
...
src/
hooks/
useForecast.js
...
index.js
routes/
weather.js
onecall.js
Here are the breakdown of each file(only includes relevant codes):
index.js(express entry file):
app.use('/weather', require('./routes/weather'))
app.use('/onecall', require('./routes/onecall'))
weather.js(1st API call):
router.get('/', async (req, res, next) => {
try {
const params = new URLSearchParams({
...url.parse(req.url, true).query, //location value from useForecast.js
appid: API_KEY
})
const apiRes = await needle('get', `${BASE_URL}/weather?${params}`) //api.openweathermap.org/data/2.5/weather?q=somecity&appid={API_KEY}
const data = apiRes.body //data will be used in useForecast.js
res.status(200).json(data)
} catch(error) {
next(error)
}
})
onecall.js(2nd API call):
router.get('/', async (req, res, next) => {
try {
const params = new URLSearchParams({
...url.parse(req.url, true).query, //lat and lat value from useForecast.js
appid: API_KEY
})
const apiRes = await needle('get', `${BASE_URL}/onecall?${params}`) //api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={lon}&appid={API_KEY}
const data = apiRes.body //data will be used in useForecast.js
res.status(200).json(data)
} catch (error) {
next(error)
}
})
useForecast.js(hook call from React):
const useForecast = () => {
...
const getCoordinates = async location => {
const { data } = await axios(`/weather?q=${location.value}`) //url from weather.js
if(data.cod === '404' || !data) {
setError(data.message)
setLoading(false)
return
}
return data
}
const getForecastData = async (lat, lon) => {
const { data } = await axios(`/onecall?lat=${lat}&lon=${lon}`) //url from onecall.js
if(data.cod === '400' || !data) {
setError('something went wrong')
setLoading(false)
return
}
return data
}
...
}
Can both calls in weather.js and onecall.js be refactored and combined into one? If so would changes in useForecast.js have to be made also?
Thanks in advance!!!