reactjs - 在自定义快速路由中使用 useEffect 时无法执行反应状态更新错误
问题描述
我的自定义快递路线有问题。每次我通过自定义路由组件更改页面时,我都会收到一个 react no-op 错误:
警告:无法对未安装的组件执行 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,如果我手动设置“授权”数组和“isFetchingAuthorizations”它工作正常。问题似乎来自http请求中的setter(如果我只评论setter,它也可以正常工作......)
编辑 3:我在我的空组件中添加了一个 useEffect 来获取我的所有用户并显示它,它像所有其他组件一样抛出警告。我想问题出在组件中有一个 useEffect ......
编辑4:我在我的空组件的useEffect中添加了一个console.log,似乎即使没有返回组件,也会触发useEffect!这可能是这里的问题!
编辑 5:问题似乎来自每个路由之间保持“授权”状态这一事实,因此当用户要求新路由时,“自动”状态由前一页授权数组填充......不知道如何修复它,我正在尝试在路线服务后清空它......如果没有人有一些提示
解决方案
对于您的情况,我有一个建议,如下所示:
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
}
})
希望能帮到你!
推荐阅读
- vue.js - 防止 v-autocomplete 在选择选项时同步搜索
- javascript - 如何将字符串传递给反应组件并将其视为 html?
- python - 即使发生错误如何继续执行
- bash - 如何修改 $0?
- c# - 在 ASP.NET Core 的外部库中使用 HttpClient
- vba - 我想在关闭后重新打开演示文稿时打开幻灯片 7
- python-3.x - 在 Centos 7.6 上将 python-3.8.9 源代码构建为 rpm 包时出现“SyntaxError: invalid syntax error”
- mysql - 如何在 mysql 中合并两个选择长度的结果?
- java - 正则表达式匹配 Java 中的首字母缩略词
- http - 如果某些权限检查失败,我如何提前终止我的处理程序?