我正在开发一个 React 应用程序,我需要在使用 Axios 拦截器的 API 调用期间显示加载程序。但是,我遇到了一个问题,即在收到响应后将加载器状态设置为 false 会导致无限循环。
这是我的代码:
import React, { useEffect, useState } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import axios from 'axios';
import { Home, About, Gallery, Packages, Policy } from './pages';
import './App.css';
import Layout from '../Layout.jsx';
import Loader from './components/Loader';
function App() {
const [isLoading, setLoading] = useState(false)
useEffect(() => {
axios.interceptors.request.use(function (config) {
console.log(config)
setLoading(true)
return config;
}, function (error) {
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
// setLoading(false)
console.log(response)
return response;
}, function (error) {
return Promise.reject(error);
})
},[])
return (
<>
{isLoading ? (
<Loader />
) : (
<BrowserRouter>
<Routes>
<Route path='/' element={<Layout />}>
<Route index element={<Home />} />
<Route path='about' element={<About />} />
<Route path='gallery' element={<Gallery />} />
<Route path='packages/:type' element={<Packages />} />
<Route path='policy/:type' element={<Policy />} />
</Route>
</Routes>
</BrowserRouter>
)}
</>
);
}
export default App;
仅当 setLoading(false) 取消注释时才会出现无限循环。
我实现了 Axios 拦截器,在请求开始时将 isLoading 状态设置为 true,在收到响应时将 isLoading 状态设置为 false。
在响应拦截器中设置setLoading(false)时,加载器会进入显示和隐藏的无限循环。这个问题似乎是由拦截器中的状态更新触发的连续重新渲染引起的。
发生无限循环是因为在 axios 拦截器内设置状态(如 setLoading(false))会导致组件重新渲染。重新渲染时,useEffect 钩子会重新执行,重新注册拦截器,这会再次导致状态更改,从而创建无限循环。为了避免这种情况,您应该添加仅注册一次的拦截器。以下是您可以做到这一点的方法,
添加use ref来存储拦截器注册状态
const isInterceptorRegistered = useRef(false);
在你的 useEffect 挂钩中执行此更改,
useEffect(() => {
if (!isInterceptorRegistered.current) {
isInterceptorRegistered.current = true;
// Request interceptor
const requestInterceptor = axios.interceptors.request.use(
//
);
// Response interceptor
const responseInterceptor = axios.interceptors.response.use(
//
);
// Cleanup interceptors on unmount
return () => {
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);
};
}
}, []);