Contemporarily, It is very easy to build a web application using Javascript Frame. In these frameworks, it is quite easy to fetch data from a remote source or consume a API.
React is the one of the most popular frontend framework out there.While learning React, you will eventually get to a point when you need to integrate APIs in your React application.Fetching data from API, let us know how to successfully communicate with information from a remote source using Axios.
We will be building a simple application that display global loading progress bar. We will make use of this endpoint, it contains a JSON dump of data needed for our contact list application.
. . .
Finally, let’s hook this up to React BoilerPlate. Its is A highly scalable, offline-first foundation with the best developer experience and a focus on performance and best practices of a web application.
First, let’s create a React Boilerplate component to keep track of the loading state.
Run command
Npm run generate
Select container option and name it MyLoader
Inside the Myloader component, we are going to define its actions.
We will be a create two dispatchable action for start and stop our loader.
https://gist.github.com/goelshobhit/e6e0f4ef019c5c7d045bde1ac6a8c628.js
Inside its index.js file, we simply call a material dialog and in the dialog content, we render the material circular loader.
To install and save in your package.json dependencies, run:
// with npm
npm install @material-ui/core
// with yarn
yarn add @material-ui/core
Please note that react >= 16.8.0 and react-dom >= 16.8.0 are peer dependencies.
https://gist.github.com/goelshobhit/f93b380a15c882d5ef447db928b73736
Our UI is ready now :D
Now, we are going to setup “MyLaoder” container. We created two actions, now we are going to use them.
Inside the container reducer, we initial declare a state, which controls the render view of the container and name its “ show loader”
https://gist.github.com/goelshobhit/68a590000d7a7826590cff3436df551f
Inside the selector , we will select our state.
import { createSelector } from 'reselect';
import { initialState } from './reducer';
/**
* Direct selector to the myLoader state domain
*/
const selectMyLoaderDomain = state => state.myLoader || initialState;
/**
* Other specific selectors
*/
/**
* Default selector used by MyLoader
*/
const makeSelectMyLoader = () =>
createSelector(
selectMyLoaderDomain,
substate => substate,
);
const makeSelectShowMyLoader = () =>
createSelector(
selectMyLoaderDomain,
substate => substate.showLoader,
);
export default makeSelectMyLoader;
export { selectMyLoaderDomain, makeSelectShowMyLoader, makeSelectMyLoader };
Previously we have our function , which controls the flow of our dialogue. As we control the container from state. So no more worries about them. Perform a small cleanUp in index.js file of “myLoader” container.
/**
*
* MyLoader
*
*/
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import Slide from '@material-ui/core/Slide';
import CircularProgress from '@material-ui/core/CircularProgress';
import { useInjectSaga } from 'utils/injectSaga';
import { useInjectReducer } from 'utils/injectReducer';
import { makeSelectMyLoader, makeSelectShowMyLoader } from './selectors';
import reducer from './reducer';
import saga from './saga';
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
export function MyLoader({ show }) {
useInjectReducer({ key: 'myLoader', reducer });
useInjectSaga({ key: 'myLoader', saga });
return (
<div>
<Dialog
open={show}
TransitionComponent={Transition}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle id="alert-dialog-slide-title">Please wait</DialogTitle>
<DialogContent
style={{
padding: '24px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
}}
>
<CircularProgress />
</DialogContent>
</Dialog>
</div>
);
}
MyLoader.propTypes = {
...MyLoader,
};
const mapStateToProps = createStructuredSelector({
myLoader: makeSelectMyLoader(),
show: makeSelectShowMyLoader(),
});
function mapDispatchToProps(dispatch) {
return {
dispatch,
};
}
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
);
export default compose(
withConnect,
memo,
)(MyLoader);
Now We have to call our API.
But this time its little bit different.
We are going to use axios and axios intercerptor.
SAGA.JS
import { call, takeLatest, put } from 'redux-saga/effects';
import request from 'utils/request';
import { LOAD_DATA } from './constants';
import { loadDataSuccess } from './actions';
function* data() {
try {
const options = {
method: 'GET',
url: `http://api.icndb.com/jokes/random?firstName=John&lastName=Doe`,
};
const res = yield call(request, options);
yield put(loadDataSuccess(res));
} catch (e) {
// do nthing
}
}
// Individual exports for testing
export default function* myLoaderSaga() {
// See example in containers/HomePage/saga.js
yield takeLatest(LOAD_DATA, data);
}
AS soon as the Axios knows to fetch the data. We have to dispatch a actions in axios interceptor. But the problem is that how to dispatch action in request.
Let go to store and perform small amount of changes.
Declare a variable.
export let configuredStore;
….
In the end of the file .
configuredStore = store;
return configuredStore;
Assign this variable to the store and return this as a store variable.
Now we can import this configedStore , anywhere in the architecture and use all the feature of our react-redux store.
import { configuredStore } from '../configureStore';
In order to dispatch action in the axios interceptor. We have to import the actions of “My loader container” inside it.
import { stopLoader, startLoader } from '../containers/MyLoader/actions';
We have to dispatch our start loader action, as soon as we call the api, means in request instance of axios.
axiosInstance.interceptors.request.use(
config => {
configuredStore.dispatch(startLoader());
return config;
},
In case of we get response from the api or we get error while calling the api we have to dispatch our “stoploader” action.
axiosInstance.interceptors.request.use(
config => {
configuredStore.dispatch(startLoader()); // when we call the api
return config;
},
err => {
configuredStore.dispatch(stopLoader()); // request error handle
return Promise.reject(err);
},
);
axiosInstance.interceptors.response.use(
response => {
configuredStore.dispatch(stopLoader()); // when we get api response
if (response.data) return response.data;
return response;
},
err => {
if (!err.response) configuredStore.dispatch(stopLoader()); // when we donot get any response
return Promise.reject(err);
},
);
That it. We completed our task.
Conclusion
In this post, we have only used Axios to make a GET request and obtain contents from an API. Axios is powerful enough to handle other HTTP request methods such as POST, PUT, PATCH and DELETE anywhere in our application. Feel free to improve on this and if you found this post useful, show some love with claps.
Comments :
Post a Comment