我想添加一个在React中进行API调用时要渲染的Loader组件。我的减速器中有一个isFetching标志,现在我可以在基于此道具的组件级别上做到这一点。但是我在全球范围内需要一个。有没有办法做到这一点?
这是我计划使用的implementation。
下面是我的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
};
请咨询。
我曾经在Angular中做过这件事,并且想要在React中做同样的事情。
答案 0 :(得分:1)
您可以在更高级别的组件(例如App)中设置 axios 拦截器。您可以使用“ SHOW_LOADER”和“ HIDE_LOADER”操作类型在减速器中定义加载状态。这些拦截器将在通过 axios 发送和接收请求之前调度相应的操作,从而更新商店中的加载状态,您可以通过该状态来呈现Loader组件。
希望这能回答您的问题。
应用组件
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{
componentWillMount(){
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 components
*/}
</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;
操作
export const loading = (bool)=>{
return bool ? {
type:"SHOW_LOADER",
data:bool
}: {
type: "HIDE_LOADER",
data: bool
}
}