How to use action creators with network request, that is how to make an API call when working with redux ?
We need to install two packages:
will be used to make get request to an api endpoint.
is the standard way to define asynchronous action creators in the application.
The Redux-thunk library is a middleware we will be applying to our redux store.
npm install axios redux-thunk
const applyMiddleware = redux.applyMiddleware;
const applyMiddleware = redux.applyMiddleware;
const thunkMiddleware = require('redux-thunk').default;
const store = createStore(reducer, applyMiddleware(thunkMiddleware));
const axios = require('axios');
Basically an action creator returns an action.
But thunkMiddleware brings the ability for an action creator to return a function instead of an action object.
const fetchUsers = () => {
// so we can now return a function.
// this function doesn't have to be pure. so it is allowed to have side effects such as async API calls.
// this function can also dispatch actions.
return function(dispatch) {
// before we fire off the API call, we dispatch fetchUserRequest to set loading to true
dispatch(fetchUsersRequest())
// get the url endpoint using JSONPlaceholder to make a get request.
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
// response data is the array of users
const users = response.data.map(user => user.id)
// dispatch fetchUsersSucess to store the user in our stsate
dispatch(fetchUsersSuccess(users))
})
.catch(error => {
// error.message is the error description
// dispatch fetchUsersFailure to display error message.
dispatch(fetchUsersFailure(error.message));
})
};
};
store.subscribe(() => {console.log(store.getState())})
store.dispatch(fetchUsers());
Import the redux-thunk
middleware and pass it to the createStore
function. What this allows is for an action creator to return a function instead of an action object. The function can now perform side effects such as asynchronous tasks. The function also can dispatch regular actions which will be handled by the reducer.
const redux = require('redux');
const createStore = redux.createStore;
const applyMiddleware = redux.applyMiddleware;
const thunkMiddleware = require('redux-thunk').default;
const axios = require('axios');
const initialState = {
loading: false,
users: [],
error: ''
};
const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST';
const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';
const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';
const fetchUsersRequest = () => {
return {
type: FETCH_USERS_REQUEST
}
};
const fetchUsersSuccess = users => {
return {
type: FETCH_USERS_SUCCESS,
payload: users
}
};
const fetchUsersFailure = error => {
return {
type: FETCH_USERS_FAILURE,
payload: error
}
};
const reducer = (state = initialState, action) => {
switch(action.type) {
case FETCH_USERS_REQUEST:
return {
...state,
loading: true
}
case FETCH_USERS_SUCCESS:
return {
loading: false,
users: action.payload,
error: ''
}
case FETCH_USERS_FAILURE:
return {
loading: false,
users: [],
error: action.payload
}
};
};
// define async actions creator
/* an action creator returns an action.
But thunkMiddleware brings the ability for an action creator to return a function instead of an action object. */
const fetchUsers = () => {
// so we can now return a function.
// this function doesn't have to be pure. so it is allowed to have side effects such as async API calls.
// this function can also dispatch actions.
return function(dispatch) {
// before we fire off the API call, we dispatch fetchUserRequest to set loading to true
dispatch(fetchUsersRequest())
// get the url endpoint using JSONPlaceholder to make a get request.
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
// response data is the array of users
const users = response.data.map(user => user.id)
// dispatch fetchUsersSucess to store the user in our stsate
dispatch(fetchUsersSuccess(users))
})
.catch(error => {
// error.message is the error description
// dispatch fetchUsersFailure to display error message.
dispatch(fetchUsersFailure(error.message));
})
};
};
const store = createStore(reducer, applyMiddleware(thunkMiddleware));
// subscribe our store
store.subscribe(() => {console.log(store.getState())})
// dispatch the async action creator
store.dispatch(fetchUsers());
node asyncActions
{ loading: true, users: [], error: '' }
{ loading: false,
users: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
error: '' }