I would like to add a Loader ponent to be rendered whenever an API call is being made in React. I have an isFetching flag in my reducer and now I am able to do it on a ponent level based on this prop. But I need one globally. Is there a way to achieve this?
This is the implementation I am planning to use.
Below is my dataService:
//if dev mode them URL prefix = http://127.0.0.1:8080/
//else
// prefix= .
// url= prefix + /users/xyz
import axios from 'axios';
const DEV_MODE_URL_PREFIX = '/api/';
const PROD_MODE_URL_PREFIX = './api/';
const ENV = process.env.NODE_ENV;
function getService(relativeUrl, options) {
return dataService(relativeUrl, options);
}
function postService(relativeUrl, dataToPost, options) {
return dataService(relativeUrl, options, dataToPost);
}
function dataService(relativeUrl, options, dataToPost) {
/**
* dataToPost = {
* key: value
* } || string
* options = {
* actions: {
* requestAction: function ()
* successAction: function (response)
* failureAction: function (error)
* },
* shouldRequest: function (state)
* }
*/
return (dispatch, getState) => {
let url;
const { requestAction, successAction, failureAction } = options.actions;
if (relativeUrl.match(/json/)) {
url = relativeUrl;
} else {
if (relativeUrl[0] === '/') {
relativeUrl = relativeUrl.slice(1);
}
if (relativeUrl[relativeUrl.length - 1] !== '/') {
relativeUrl += '/';
}
if (ENV !== 'production') {
url = DEV_MODE_URL_PREFIX + relativeUrl;
} else {
url = PROD_MODE_URL_PREFIX + relativeUrl;
}
}
if (options.shouldRequest(getState())) {
let promise;
const data = typeof dataToPost === 'string' ? { 'data': dataToPost } : dataToPost;
dispatch(requestAction());
promise = dataToPost ? axios.post(url, data, { withCredentials: true }) : axios.get(url, { withCredentials: true });
return promise
.then(response => {
console.log(
`status: ${response.status}
message: ${response.message}`
);
if (response.status === 200) {
return dispatch(successAction(response, dispatch));
}
return Promise.reject(response);
})
.catch(error => {
console.log(error);
return dispatch(failureAction(error));
});
} else {
return Promise.reject('FETCHING');
}
};
}
export {
getService,
postService
};
Please advice.
I have earlir done it in Angular and would like the same thing in React.
I would like to add a Loader ponent to be rendered whenever an API call is being made in React. I have an isFetching flag in my reducer and now I am able to do it on a ponent level based on this prop. But I need one globally. Is there a way to achieve this?
This is the implementation I am planning to use.
Below is my dataService:
//if dev mode them URL prefix = http://127.0.0.1:8080/
//else
// prefix= .
// url= prefix + /users/xyz
import axios from 'axios';
const DEV_MODE_URL_PREFIX = '/api/';
const PROD_MODE_URL_PREFIX = './api/';
const ENV = process.env.NODE_ENV;
function getService(relativeUrl, options) {
return dataService(relativeUrl, options);
}
function postService(relativeUrl, dataToPost, options) {
return dataService(relativeUrl, options, dataToPost);
}
function dataService(relativeUrl, options, dataToPost) {
/**
* dataToPost = {
* key: value
* } || string
* options = {
* actions: {
* requestAction: function ()
* successAction: function (response)
* failureAction: function (error)
* },
* shouldRequest: function (state)
* }
*/
return (dispatch, getState) => {
let url;
const { requestAction, successAction, failureAction } = options.actions;
if (relativeUrl.match(/json/)) {
url = relativeUrl;
} else {
if (relativeUrl[0] === '/') {
relativeUrl = relativeUrl.slice(1);
}
if (relativeUrl[relativeUrl.length - 1] !== '/') {
relativeUrl += '/';
}
if (ENV !== 'production') {
url = DEV_MODE_URL_PREFIX + relativeUrl;
} else {
url = PROD_MODE_URL_PREFIX + relativeUrl;
}
}
if (options.shouldRequest(getState())) {
let promise;
const data = typeof dataToPost === 'string' ? { 'data': dataToPost } : dataToPost;
dispatch(requestAction());
promise = dataToPost ? axios.post(url, data, { withCredentials: true }) : axios.get(url, { withCredentials: true });
return promise
.then(response => {
console.log(
`status: ${response.status}
message: ${response.message}`
);
if (response.status === 200) {
return dispatch(successAction(response, dispatch));
}
return Promise.reject(response);
})
.catch(error => {
console.log(error);
return dispatch(failureAction(error));
});
} else {
return Promise.reject('FETCHING');
}
};
}
export {
getService,
postService
};
Please advice.
I have earlir done it in Angular and would like the same thing in React.
Share Improve this question asked Feb 28, 2019 at 20:46 arunmmanoharanarunmmanoharan 2,6773 gold badges37 silver badges74 bronze badges1 Answer
Reset to default 3You can setup axios interceptors in a higher level ponent let's say App. You can define a loading state in the reducer with "SHOW_LOADER" & "HIDE_LOADER" action types. These interceptors will dispatch the corresponding actions before a request is sent and received via axios, updating the loading state in store through which you can render a Loader ponent.
Hope this answers your question.
App Component
import React from 'react';
import axios from 'axios'
import { connect } from 'react-redux';
import { loading } from '../actions'
import Loader from './Loader'
class App extends React.Component{
ponentWillMount(){
const self = this
axios.interceptors.request.use(function (config) {
// spinning start to show
self.props.loading(true)
return config
}, function (error) {
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
// spinning hide
self.props.loading(false)
return response;
}, function (error) {
return Promise.reject(error);
});
}
render(){
return (
<div>
{ this.props.loader ? <Loader /> : null }
{/*
Your other ponents
*/}
</div>
)
}
}
const mapStateToProps = (state)=>{
return {
loader: state.loader
}
}
export default connect(mapStateToProps,{
loading
})(App);
Loader Reducer
const loader = (state = false, action) => {
switch (action.type) {
case "SHOW_LOADER":
return action.data;
break;
case "HIDE_LOADER":
return action.data;
break;
default:
return state;
}
}
export default loader;
Action
export const loading = (bool)=>{
return bool ? {
type:"SHOW_LOADER",
data:bool
}: {
type: "HIDE_LOADER",
data: bool
}
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745232418a4617738.html
评论列表(0条)