Yesterday we have seen how to set up a basic application that fetches the NASA photo of the day.
Our application has a button that when clicked fires out an action that connects to the NASA API
and asynchronously fetches some data, including an image. We then display this image in our view.
Application states
We can think of our application having multiple states.
The initial state is just a blank page.
When we click the Fetch button, we enter into the LOADING
state.
In the LOADING
state we have initiated the API
call and we are waiting to see if we get data back from the remote server.
In our example, we are going to show a loading animation while in this state, so the user has some visual feedback that something is happening.
Once our API
called is resolved, we pass from the LOADING
state to either a SUCCESS
state or a FAILURE
state, depending if our call was successful or not.
If the call is successful, we transition into a SUCCESS
state and display the data received to the screen.
If the call is unsuccessful, we transition into a FAILURE
state and we display an error message.
From this description, we gather that the action creator handling this button click needs to be able to dispatch three different actions to the reducer: FETCH_PHOTO_START
, FETCH_PHOTO_SUCCESS
, FETCH_PHOTO_FAILURE
.
We call our action creator getPhoto
and we define it in a new index.js
file inside src/actions/
mkdir actions
touch actions/index.js
Let's start small by just handling FETCH_PHOTO_START
.
Remember, an action creator is a function that returns an object with a mandatory type
property and an optional payload
property.
The type we want to return is FETCH_PHOTO_START
Here's our action so far:
// src/actions/index.js
export const FETCH_PHOTO_START = 'FETCH_PHOTO_START';
export const getPhoto = () => {
return {
type: FETCH_PHOTO_START
}
}
We need to make our application aware that we are in the LOADING
state, so we add a new property to our state called isLoading
, initially set to false
. We will switch it to true
when the transition to the LOADING
state starts.
In our reducer, we add the new property to the initial state:
// src/reducers/index.js
const initialState = {
// ... existing code ...
isLoading: false
}
We also add a switch
statement to the reducer so we can return a new version of the state with the isLoading
property set to true
when FETCH_PHOTO_START
is received:
// src/reducers/index.js
const reducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_PHOTO_START: {
return {
...state,
isLoading: true
}
}
default: return state;
}
}
Since we are using a new state property, we need to add it to our mapStateToProps
function in the NASAPhoto
component:
// src/components/NASAPhoto.js
const mapStateToProps = state => {
return {
// ... existing code ...
isLoading: state.isLoading
}
}
We said we are going to show a loading spinner so we add a dependency called react-loader-spinner
:
npm install react-loader-spinner
Once it's installed, we can use it in our component by importing it and configuring it through props.
Note that we show the spinner only when isLoading
is true
, so we check for that condition and if it's true we add the spinner component:
// src/components/NASAPhoto.js
import Loader from 'react-loader-spinner';
const NASAPhoto = props => {
return (
<>
// ... existing code ...
{ props.isLoading && (
<Loader type="BallTriangle" height={90} width={60} color="#00BFFF" />
)}
</>
)
}
Note: height
and width
in the Loader
need to be numbers, it will give an error if we type height="90"
because that's a string, so we need to interpolate the number inside braces as the prop
value.
At this point, everything should be ready to load a spinner when our application goes into a LOADING
state and isLoading
is true.
But how do we trigger this change of state?
We will trigger the state change when we click the Fetch button so we need to add an onClick
event listener and create a function that fires the FETCH_PHOTO_START
action when the event is detected.
We'll do this tomorrow.
Did you like this article? Share it with your friends.
I write daily about front-end and back-end web technologies. You can receive all my articles in your inbox by subscribing to my newsletter. Just click the button below. No spam, just good, useful content. Guaranteed!