[英]PrivateRoute functional component using aws-amplify as authentication
I'm trying to create a functional component equivalent of the following PrivateRoute class component (source code here ):我正在尝试创建一个等效于以下 PrivateRoute 类组件的功能组件(源代码在这里):
import React, { useState, useEffect } from "react";
import { Route, Redirect, withRouter, useHistory } from "react-router-dom";
import { Auth } from "aws-amplify";
class PrivateRoute extends React.Component {
state = {
loaded: false,
isAuthenticated: false
};
componentDidMount() {
this.authenticate();
this.unlisten = this.props.history.listen(() => {
Auth.currentAuthenticatedUser()
.then(user => console.log("user: ", user))
.catch(() => {
if (this.state.isAuthenticated)
this.setState({ isAuthenticated: false });
});
});
}
componentWillUnmount() {
this.unlisten();
}
authenticate() {
Auth.currentAuthenticatedUser()
.then(() => {
this.setState({ loaded: true, isAuthenticated: true });
})
.catch(() => this.props.history.push("/auth"));
}
render() {
const { component: Component, ...rest } = this.props;
const { loaded, isAuthenticated } = this.state;
if (!loaded) return null;
return (
<Route
{...rest}
render={props => {
return isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/auth"
}}
/>
);
}}
/>
);
}
}
export default withRouter(PrivateRoute);
The above code works in my application when I use it like so:当我像这样使用它时,上面的代码在我的应用程序中工作:
<PrivateRoute
exact
path={urls.homepage}
component={Homepage}
/>
My attempt at a converting the above class component into a functional component is the following:我将上述类组件转换为功能组件的尝试如下:
import React, { useState, useEffect } from "react";
import { Route, Redirect, useHistory } from "react-router-dom";
import { Auth } from "aws-amplify";
const PrivateRoute = ({ component: Component, ...rest }) => {
const [isLoaded, setIsLoaded] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState(false);
let history = useHistory();
useEffect(() => {
Auth.currentAuthenticatedUser()
.then(() => {
setIsLoaded(true);
setIsAuthenticated(true);
})
.catch(() => history.push("/auth"));
return () =>
history.listen(() => {
Auth.currentAuthenticatedUser()
.then(user => console.log("user: ", user))
.catch(() => {
if (isAuthenticated) setIsAuthenticated(false);
});
});
}, [history, isAuthenticated]);
if (!isLoaded) return null;
return (
<Route
{...rest}
render={props => {
return isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/auth"
}}
/>
);
}}
/>
);
};
export default PrivateRoute;
But when using my functional component in the same way, I keep getting the following error:但是当以同样的方式使用我的功能组件时,我不断收到以下错误:
Warning: Can't perform a React state update on an unmounted component.
警告:无法对卸载的组件执行 React 状态更新。 This is a no-op, but it indicates a memory leak in your application.
这是一个空操作,但它表明您的应用程序中存在内存泄漏。 To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function
修复,取消 useEffect 清理函数中的所有订阅和异步任务
It always redirects me to /auth, regardless of whether I am logged in or not.它总是将我重定向到 /auth,无论我是否登录。 What am I doing wrong?
我究竟做错了什么? Any help is much appreciated!
任何帮助深表感谢!
I think you are missing your unmount, the return in the useEffect
should be your unlisten
which is the unmount.我认为您错过了卸载,
useEffect
的返回应该是您的unlisten
,即卸载。 Also, I removed useHistory
and pulled history
from the props and used withRouter
另外,我删除了
useHistory
并从道具中提取了history
并使用了withRouter
Try this尝试这个
import React, { useState, useEffect } from "react";
import { Route, Redirect, withRouter } from "react-router-dom";
import { Auth } from "aws-amplify";
const PrivateRoute = ({ component: Component, history, ...rest }) => {
const [isLoaded, setIsLoaded] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
Auth.currentAuthenticatedUser()
.then(() => {
setIsLoaded(true);
setIsAuthenticated(true);
})
.catch(() => history.push("/auth"));
const unlisten = history.listen(() => {
Auth.currentAuthenticatedUser()
.then(user => console.log("user: ", user))
.catch(() => {
if (isAuthenticated) setIsAuthenticated(false);
});
});
return unlisten();
}, [history, isAuthenticated]);
if (!isLoaded) return null;
return (
<Route
{...rest}
render={props => {
return isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/auth"
}}
/>
);
}}
/>
);
};
export default withRouter(PrivateRoute);
Try this out:试试这个:
useEffect(() => {
async function CheckAuth() {
await Auth.currentAuthenticatedUser()
.then((user) => {
setIsLoaded(true);
setIsAuthenticated(true);
})
.catch(() => history.push("/auth"));
}
CheckAuth();
}, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.