使用useEffect
钩子时,我似乎收到以下错误。
警告:无法对卸载的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。
我相信它与我调用的异步函数有关,以设置用户是否经过身份验证。
ProtectedRoute.tsx
export function ProtectedRoute({ ...routeProps }: ProtectedRouteProps): ReactElement | null {
const context = useContext(AppContext);
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
isUserAuthenticated(context.token).then(setIsAuthenticated).catch(setIsAuthenticated);
});
if (isAuthenticated) {
return <Route {...routeProps} />;
} else {
return <Redirect to={{ pathname: "login" }} />;
}
}
const isUserAuthenticated = async (token: any): Promise<boolean> => {
try {
const response = await VerifyAuthentication(token);
console.log("VerifyAuthentication", response);
if (response.status !== 200) {
return false;
}
return true;
} catch (err) {
return false;
}
};
应用程序.tsx
class App extends Component<Props, State> {
renderRouter = () => {
return (
<Router>
<Switch>
<ProtectedRoute exact path="/" component={Dashboard} />
<Route exact path="/login" component={Login} />
</Switch>
</Router>
);
};
render(): ReactElement {
return (
<div className="App">
<AppProvider>
<Theme>
<Sidebar>{this.renderRouter()}</Sidebar>
</Theme>
</AppProvider>
</div>
);
}
}
大概这会将用户重定向到没有此组件的路由:
return <Redirect to={{ pathname: "login" }} />;
这意味着组件已卸载,或者通常从活动使用/内存中卸载。这总是发生,因为这种情况永远不会是true
:
if (isAuthenticated) {
因为当组件首次呈现该值时,该值显式设置为false
:
const [isAuthenticated, setIsAuthenticated] = useState(false);
所以基本上发生的事情是:
尚不完全清楚该组件打算如何适应您的整体结构,但您将需要更改该结构。检查身份验证需要同步,或者您需要在重定向之前等待异步操作完成。后者的一个例子可能很简单:
export function ProtectedRoute({ ...routeProps }: ProtectedRouteProps): ReactElement | null {
const context = useContext(AppContext);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
isUserAuthenticated(context.token)
.then(x => {
setIsAuthenticated(x);
setIsLoading(false);
})
.catch(e => {
setIsAuthenticated(false);
setIsLoading(false);
console.log(e);
});
});
if (isLoading) {
return <div>Loading...</div>;
} else if (isAuthenticated) {
return <Route {...routeProps} />;
} else {
return <Redirect to={{ pathname: "login" }} />;
}
}
在这种情况下,单独的状态值isLoading
用于跟踪异步操作是否仍在发生,因此组件“等待”直到数据加载,然后再决定是否重定向用户。
但总的来说,我不明白为什么身份验证检查不能同步。更高级别的东西,例如将整个应用程序结构包装在 中的提供者组件<App/>
,可以具有上述相同的逻辑,本质上执行异步操作并将结果保持在状态。然后可以通过useContext
或 Redux提供该状态,甚至可以将其作为道具传递给所有子组件。
您不需要在子组件中一遍又一遍地重新检查身份验证。这是应用程序级别的问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句