reactjs - React PrivateRoute 身份验证和未解决的令牌承诺问题
问题描述
我有一个想要为其创建 PrivateRoutes 的反应应用程序。以下是PrivateRoute.tsx
文件:
import * as React from 'react';
import { Route,Redirect, RouteProps} from 'react-router-dom';
import { getToken } from '../../auth/auth';
interface PrivateRouteProps extends RouteProps {
component?: any;
children?: any;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, children, ...rest } = props;
const [isAuthenticated, setAuth ] = useState(false);
useEffect(() => {
async function fetchToken() {
try {
const token = await getToken();
if (token && token.length) {
setAuth(true);
} else {
setAuth(false);
}
} catch(e) {
console.log(e);
setAuth(false);
}
}
fetchToken();
}, [isAuthenticated]);
return (
<Route
{...rest}
render={routeProps =>
isAuthenticated ? (
Component ? (
<Component {...routeProps} />
) : (
children
)
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: routeProps.location },
}}
/>
)
}
/>
);
};
export default PrivateRoute;
以下是我在 App.tsx 文件中的路由设置
//...
const App = () => {
return (
<div className="application">
<Router>
<Switch>
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
<NavBar>
<Switch>
<PrivateRoute path="/tasks" component={Tasks}/>
<PrivateRoute path="/people" component={People}/>
</Switch>
</NavBar>
<Route component={NotFound} />
<Redirect from="/" to="/signin" exact={true} />
</Switch>
</Router>
</div>
);
};
export default App;
令牌存储在 LocalForage 中。上面的代码产生以下警告,我无法访问 PrivateRoutes。我怀疑这是因为组件在承诺得到解决并且令牌可用之前被返回。
Warning: Can't perform a React state update on an unmounted component. 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.
我会感谢有用的答案。
解决方案
尝试在令牌获取未完成时添加某种加载器,因为您的PrivateRoute
立即返回Redirect
会将您重定向到另一个组件,但是由于您尚未取消您的承诺,一旦完成,它将调用实际上未安装的加载器,这将setAuth
导致PrivateRoute
你有这个问题。
例子:
import * as React from 'react';
import { Route,Redirect, RouteProps} from 'react-router-dom';
import { getToken } from '../../auth/auth';
interface PrivateRouteProps extends RouteProps {
component?: any;
children?: any;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, children, ...rest } = props;
const [isAuthenticated, setAuth ] = useState(false);
const [isAuthenticating, setIsAuthenticating] = useState(true);
useEffect(() => {
async function fetchToken() {
try {
setIsAuthenticating(true);
const token = await getToken();
if (token && token.length) {
setAuth(true);
} else {
setAuth(false);
}
} catch(e) {
console.log(e);
setAuth(false);
} finally {
setIsAuthenticating(false);
}
}
fetchToken();
}, [isAuthenticated]);
if (isAuthenticating) {
return <span>Loading...</span>
}
return (
<Route
{...rest}
render={routeProps =>
isAuthenticated ? (
Component ? (
<Component {...routeProps} />
) : (
children
)
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: routeProps.location },
}}
/>
)
}
/>
);
};
export default PrivateRoute;
推荐阅读
- python - 限制删除 django 模型值的问题
- reactjs - 如何在登录页面上使用 React Router Link?
- python - 更新 JSON 文件的键值
- python - 通过删除 [] 更改 Python 子字符串
- tensorflow - 刚刚从 anaconda 重新安装了 keras-gpu,并收到了关于使用 windows 10 的 tensorflow 的弃用警告
- c++ - 初始化面向对象的数组 C++
- javascript - 如何使用 JS 脚本在同一个文件中运行 mocha
- javascript - 每次数据可用时,如何一次将三个项目附加到一行中?
- grails - 有没有办法用 hasOne 孩子懒惰地获取 GORM 实体?
- sql-server - 聚合查询 SQL Server 中的示例 ID