React Hooks:使用 axios 拦截器显示全局微调器?
React Hooks: Display global spinner using axios interceptor?
我想添加一个加载器组件,以便在 React 中进行 API 调用时呈现。我想使用 react context + hooks 而不是 redux.
正如react hooks的规则所说,我们不应该在react组件之外使用react hooks。但是我需要在 Axios 拦截器中发送 SHOW_LOADER
和 HIDE_LOADER
,如下所示。
有办法实现吗?
import axios from "axios";
axios.interceptors.request.use(
config => {
dispatch({
type: "SHOW_LOADER"
})
return config;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
axios.interceptors.response.use(
response => {
dispatch({
type: "HIDE_LOADER"
})
return response;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
function GlobalLoader(){
const [state,dispatch] = useContext(LoaderContext);
return(
<div>
{
state.loadStatus &&
<Loader
type = "Puff"
color = "#00BFFF"
height = {100}
width = {100}
timeout = {3000} />
}
</div>
);
}
export default GlobalLoader;
如果需要更多信息,请告诉我。:)
使用 axios.create(config)
创建一个 axios 实例。在 useEffect()
中使用这个实例来添加可以影响状态的拦截器(减速器在这里是一个矫枉过正)。现在到处使用实例,拦截器会导致状态发生变化。
注意:由于多个请求可以start/and或结束,所以应该使用计数器。根据请求递增,根据响应递减。如果计数器不是 0
,应用程序正在加载。
const { useState, useMemo, useEffect } = React;
const ax = axios.create(); // export this and use it in all your components
const useAxiosLoader = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const inc = mod => setCounter(c => c + mod);
const handleRequest = config => (inc(1), config);
const handleResponse = response => (inc(-1), response);
const handleError = error => (inc(-1), Promise.reject(error));
// add request interceptors
const reqInterceptor = ax.interceptors.request.use(handleRequest, handleError);
// add response interceptors
const resInterceptor = ax.interceptors.response.use(handleResponse, handleError);
return () => {
// remove all intercepts when done
ax.interceptors.request.eject(reqInterceptor);
ax.interceptors.response.eject(resInterceptor);
};
}, []);
return counter > 0;
};
const GlobalLoader = () => {
const loading = useAxiosLoader();
return(
<div>
{
loading ? 'loading' : 'not loading'
}
</div>
);
}
const callApi = (err) => ax.get(err ? 'https://asdf' : 'https://www.boredapi.com/api/activity')
// make a request by using the axios instance
setTimeout(() => {
callApi();
callApi(true);
callApi();
}, 1000);
ReactDOM.render(
<GlobalLoader />,
root
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
旧版本:
const { useState, useMemo, useEffect } = React;
const ax = axios.create(); // export this and use it in all your components
const useAxiosLoader = () => {
const [counter, setCounter] = useState(0);
const interceptors = useMemo(() => {
const inc = () => setCounter(counter => counter + 1);
const dec = () => setCounter(counter => counter - 1);
return ({
request: config => (inc(), config),
response: response => (dec(), response),
error: error => (dec(), Promise.reject(error)),
});
}, []); // create the interceptors
useEffect(() => {
// add request interceptors
const reqInterceptor = ax.interceptors.request.use(interceptors.request, interceptors.error);
// add response interceptors
const resInterceptor = ax.interceptors.response.use(interceptors.response, interceptors.error);
return () => {
// remove all intercepts when done
ax.interceptors.request.eject(reqInterceptor);
ax.interceptors.response.eject(resInterceptor);
};
}, [interceptors]);
return [counter > 0];
};
const GlobalLoader = () => {
const [loading] = useAxiosLoader();
return(
<div>
{
loading ? 'loading' : 'not loading'
}
</div>
);
}
const callApi = (err) => ax.get(err ? 'https://asdf' : 'https://www.boredapi.com/api/activity')
// make a request by using the axios instance
setTimeout(() => {
callApi();
callApi(true);
callApi();
}, 1000);
ReactDOM.render(
<GlobalLoader />,
root
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
我想添加一个加载器组件,以便在 React 中进行 API 调用时呈现。我想使用 react context + hooks 而不是 redux.
正如react hooks的规则所说,我们不应该在react组件之外使用react hooks。但是我需要在 Axios 拦截器中发送 SHOW_LOADER
和 HIDE_LOADER
,如下所示。
有办法实现吗?
import axios from "axios";
axios.interceptors.request.use(
config => {
dispatch({
type: "SHOW_LOADER"
})
return config;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
axios.interceptors.response.use(
response => {
dispatch({
type: "HIDE_LOADER"
})
return response;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
function GlobalLoader(){
const [state,dispatch] = useContext(LoaderContext);
return(
<div>
{
state.loadStatus &&
<Loader
type = "Puff"
color = "#00BFFF"
height = {100}
width = {100}
timeout = {3000} />
}
</div>
);
}
export default GlobalLoader;
如果需要更多信息,请告诉我。:)
使用 axios.create(config)
创建一个 axios 实例。在 useEffect()
中使用这个实例来添加可以影响状态的拦截器(减速器在这里是一个矫枉过正)。现在到处使用实例,拦截器会导致状态发生变化。
注意:由于多个请求可以start/and或结束,所以应该使用计数器。根据请求递增,根据响应递减。如果计数器不是 0
,应用程序正在加载。
const { useState, useMemo, useEffect } = React;
const ax = axios.create(); // export this and use it in all your components
const useAxiosLoader = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const inc = mod => setCounter(c => c + mod);
const handleRequest = config => (inc(1), config);
const handleResponse = response => (inc(-1), response);
const handleError = error => (inc(-1), Promise.reject(error));
// add request interceptors
const reqInterceptor = ax.interceptors.request.use(handleRequest, handleError);
// add response interceptors
const resInterceptor = ax.interceptors.response.use(handleResponse, handleError);
return () => {
// remove all intercepts when done
ax.interceptors.request.eject(reqInterceptor);
ax.interceptors.response.eject(resInterceptor);
};
}, []);
return counter > 0;
};
const GlobalLoader = () => {
const loading = useAxiosLoader();
return(
<div>
{
loading ? 'loading' : 'not loading'
}
</div>
);
}
const callApi = (err) => ax.get(err ? 'https://asdf' : 'https://www.boredapi.com/api/activity')
// make a request by using the axios instance
setTimeout(() => {
callApi();
callApi(true);
callApi();
}, 1000);
ReactDOM.render(
<GlobalLoader />,
root
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
旧版本:
const { useState, useMemo, useEffect } = React;
const ax = axios.create(); // export this and use it in all your components
const useAxiosLoader = () => {
const [counter, setCounter] = useState(0);
const interceptors = useMemo(() => {
const inc = () => setCounter(counter => counter + 1);
const dec = () => setCounter(counter => counter - 1);
return ({
request: config => (inc(), config),
response: response => (dec(), response),
error: error => (dec(), Promise.reject(error)),
});
}, []); // create the interceptors
useEffect(() => {
// add request interceptors
const reqInterceptor = ax.interceptors.request.use(interceptors.request, interceptors.error);
// add response interceptors
const resInterceptor = ax.interceptors.response.use(interceptors.response, interceptors.error);
return () => {
// remove all intercepts when done
ax.interceptors.request.eject(reqInterceptor);
ax.interceptors.response.eject(resInterceptor);
};
}, [interceptors]);
return [counter > 0];
};
const GlobalLoader = () => {
const [loading] = useAxiosLoader();
return(
<div>
{
loading ? 'loading' : 'not loading'
}
</div>
);
}
const callApi = (err) => ax.get(err ? 'https://asdf' : 'https://www.boredapi.com/api/activity')
// make a request by using the axios instance
setTimeout(() => {
callApi();
callApi(true);
callApi();
}, 1000);
ReactDOM.render(
<GlobalLoader />,
root
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>