我的自定义快递路线有问题。每次通过自定义路线组件更改页面时,都会出现无操作错误
:
警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。
这是我的自定义路线组件/处理程序:
import React from 'react';
import { Route } from 'react-router-dom';
import { AuthenticationContext } from '../../contexts/authentication/context';
import Unauthorized from '../Unauthorized';
import axios from 'axios';
const ProtectedRoute = ({ component: Component, redirect: Redirect, contextProvider: ContextProvider, path, ...routeProps }) => {
const { authenticationState: {isAuthenticated, isFetchingTheUser, currentUser} } = React.useContext(AuthenticationContext)
const [authorized, setAuthorized] = React.useState(['Admin']);
const [isFetchingAuthorizations, setIsFetchingAuthorizations] = React.useState(false);
React.useEffect(() => {
console.log("useEffect from protected route")
setIsFetchingAuthorizations(true);
axios.get(`${global.REST_API_ADDR}/api/pages/${encodeURIComponent(path)}`)
.then((response) => {
setAuthorized(response.data.authorized);
setIsFetchingAuthorizations(false);
})
.catch((error) => {
setIsFetchingAuthorizations(false);
console.log("Protected route use Effect error : ", error);
})
}, [path])
return (
<Route {...routeProps}
render={ props => {
if(isFetchingTheUser || isFetchingAuthorizations) return <div>Chargement...</div>
if(isAuthenticated && authorized.includes(currentUser.rank)){
return ContextProvider ? <ContextProvider><Component {...props} /></ContextProvider> : <Component {...props} />
}else if(isAuthenticated && !authorized.includes(currentUser.rank)) {
return <Unauthorized {...props} />;
}
else{
return <Redirect {...props}/>;
}
}}/>
);
};
export default ProtectedRoute;
如果使用useEffect()删除零件,我将不再在控制台中收到警告,但是我确实需要此钩子来检查用户是否有权访问此页面
有人可以启发我吗?
预先感谢
编辑1: 我试图创建一个空组件,并通过相同的自定义路由(ProtectedRoute)访问了它,并且没有警告,该“空组件”中没有任何useEffect,这似乎是其他组件中的问题...所以当我尝试访问其中具有useEffect的组件时收到此警告...
编辑2: 通过进一步的测试,我可以确定问题出在我的ProtectedRoute组件中,它来自useEffect,如果我手动设置“ authorized”数组和“ isFetchingAuthorizations”,它可以正常工作。问题似乎出在http请求中的setter上(如果我只评论setter,它也可以正常工作...)
编辑3:我在空组件中添加了一个useEffect来获取所有用户并显示它,并且它像所有其他组件一样发出警告。我猜问题出在组件中有一个useEffect ...
编辑4:我在空组件的useEffect中添加了console.log,即使未返回组件,似乎也触发了useEffect!可能是这里的问题!
编辑5:问题似乎出在每个路由之间都保留了“授权”状态这一事实,因此,当用户请求新路由时,“已授权”状态充满了先前的页面授权数组...不知道如何解决,我正在尝试在送达路线后将其清空...如果海葵有一些提示
答案 0 :(得分:1)
对于您的情况,我有一个建议:
useEffect(() => {
let didCancel = false; // to trigger handle clean up
const fetchData = async () => {
try {
const result = await .get(`${global.REST_API_ADDR}/api/pages/${encodeURIComponent(path)}`);
if (!didCancel) {
setAuthorized(result...);
setIsFetchingAuthorizations(result...);
}
} catch (error) {
if (!didCancel) {
setIsFetchingAuthorizations(result...);
}
}
};
fetchData()
return {
didCancel = true; // clean up useEffect
}
})
希望可以帮助您!
答案 1 :(得分:0)
这就是我的想法,请在卸载前清理http请求。我写了一些可能对您有用的东西,尝试一下并让我知道。另外,这里是有关此https://medium.com/@selvaganesh93/how-to-clean-up-subscriptions-in-react-components-using-abortcontroller-72335f19b6f7
的有用文章useEffect(() => {
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
setIsFetchingAuthorizations(true);
const fetchData = axios.get(`${global.REST_API_ADDR}/api/pages/${encodeURIComponent(path)}`)
.then((response) => {
setAuthorized(response.data.authorized);
setIsFetchingAuthorizations(false);
})
.catch((error) => {
setIsFetchingAuthorizations(false);
console.log("Protected route use Effect error : ", error);
})
fetchData();
return () => {
source.cancel();
};
}, [path]);