Fetching a photo from a remote API with Axios and Redux middleware
Now that we have our action creator set up correctly to dispatch actions using middleware, we can go about actually fetching something from the remote API
.
To work with the remote API
we use Axios. Axios is an http
client that lets us make remote calls easily.
We first need to install it:
npm install axios
and then we import it into our action creator file:
// actions/index.js
import axios from 'axios';
Our action creator is currently only dispatching the FETCH_PHOTO_START
action. Now we need it to handle a couple more actions.
One is FETCH_PHOTO_SUCCESS
. This action will be dispatched if our Axios call is successful.
The second action to handle is FETCH_PHOTO_FAILURE
that will be dispatched if the Axios call resolves with an error.
Let's set up our Axios connection inside the action creator:
// src/actions/index.js
export const getPhoto = () => ( dispatch ) => {
dispatch({type: FETCH_PHOTO_START});
axios.get('https://api.nasa.gov/planetary/apod?api_key=<---API key --->')
.then(res => dispatch({ type: FETCH_PHOTO_SUCCESS, payload: res.data }))
.catch(err => dispatch({ type: FETCH_PHOTO_FAILURE, payload: err }))
}
We invoke the axios.get()
method passing the URL to the NASA API
, including the API
key that we have received from NASA when we signed up for API
access.
If we get a successful response, we dispatch FETCH_PHOTO_SUCCESS
with a payload of the response data.
If we get an error, we dispatch FETCH_PHOTO_FAILURE
and we send the error along as a payload, so we can see what the actual error was.
We also need to define the new constants at the top of the file:
// src/actions/index.js
export const FETCH_PHOTO_SUCCESS = 'FETCH_PHOTO_SUCCESS'
export const FETCH_PHOTO_FAILURE = 'FETCH_PHOTO_FAILURE'
Now that our action creator is all set, we need to handle the dispatched actions in the reducer.
We first import the new action type constants:
// src/reducers/index.js
import { FETCH_PHOTO_START,
FETCH_PHOTO_SUCCESS,
FETCH_PHOTO_FAILURE }
from '../actions';
Then we add two more case statements to handle success and error:
// src/reducers/index.js
const reducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_PHOTO_START: {
return {
...state,
isLoading: true
}
}
case FETCH_PHOTO_SUCCESS: {
return {
...state,
photoOfTheDay: action.payload,
isLoading: false
}
}
case FETCH_PHOTO_FAILURE: {
console.log("FAILURE PAYLOAD:", action.payload) // for testing
return {
...state,
isLoading: false
}
}
default: return state;
}
}
With these changes our photo should be retrieved correctly, but there is still a little issue to fix.
In our NASAPhoto
component, we display the photo in this way:
<img src={props.photoOfTheDay} alt="NASA pic" />
This won't show a photo because after the API call photoOfTheDay
is set to the full API
response. Within this response, the photo URL is available at photoOfTheDay.url
We may be tempted to fix this by adding .url
at the end, like this:
<img src={props.photoOfTheDay.url} alt="NASA pic" />
This would display the photo, but the problem now is that initially we display NASAPhoto
component before we even perform the Axios call.
At that point photoOfTheDay
is set to null
and if we call .url
on a null
object, we get an error that breaks our application.
There are several ways to address this issue, but we are going with the simplest way, that is: check if photoOfTheDay
is not null
, and in this case, call .url
on it and display the photo.
This is the code to achieve this:
// src/components/NASAPhoto.js
{
props.photoOfTheDay && (
<img src={props.photoOfTheDay.url} alt="NASA pic" />
)
}
And with this change, we can finally retrieve and display the NASA Photo of the day.
Previous articles in this series:
I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.
You can receive articles like this in your inbox by subscribing to my newsletter.
Top comments (1)
Well done! NASA's APOD endpoint is my personal favorite for showing friends how to do something cool with web technology.