我很难理解为什么我的Authorized
和Unauthorized
路由运行不正常。。以下是我的路线设置方式:
class App extends Component {
render() {
return (
<HashRouter>
<React.Suspense fallback={loading()}>
<Switch>
<UnauthenticatedRoute exact path="/login" name="Login Page" component={Login} />
<Route exact path="/register" name="Register Page" component={Register} />
<Route exact path="/404" name="Page 404" component={Page404} />
<Route exact path="/500" name="Page 500" component={Page500} />
<AuthenticatedRoute path="/" name="Home" component={DefaultLayout} />
</Switch>
</React.Suspense>
</HashRouter>
);
}
}
export default App;
我有一个auth.js
,它保存了所有这些路由类型,并检查JWT令牌是否有效:
import React from 'react';
import { Redirect, Route } from 'react-router-dom';
import { Api } from './api'
const isAuthenticated = () => {
Api.isActiveToken(sessionStorage.getItem('token')).then(
(response) => {
console.log(response)
return response.ok
},
(error) => {
return false
}
)
}
const AuthenticatedRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
isAuthenticated()
? <Component {...props} />
: <Redirect to='/login' />
)} />
);
const UnauthenticatedRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
!isAuthenticated()
? <Component {...props} />
: <Redirect to='/' />
)} />
);
export { AuthenticatedRoute, UnauthenticatedRoute }
console.log(response)
如下所示:
Response {type: "cors", url: "http://xxx/api/v1/login/validate-token", redirected: false, status: 200, ok: true, …}
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://xxx/api/v1/login/validate-token"
__proto__: Response
我的sessionStorage
持有代币很好。我做错了什么,以至于我的路由从未重定向/允许我到AuthorizedRoute
?
isAuthenticated()
是异步的,当前返回void。您必须使isAuthenticated返回布尔值的Promise。
一旦isAuthenticated返回了一个值,就需要使用一个效果和状态来从promise中提取实际值。
import React, { useState, useEffect } from 'react';
import { Redirect, Route } from 'react-router-dom';
import { Api } from './api';
const isAuthenticated = async () => {
try {
const response = await Api.isActiveToken(sessionStorage.getItem('token'));
return response.ok;
} catch (error) {
return false;
}
};
const AuthenticatedRoute = ({ component: Component, ...rest }) => {
const [authenticated, setAuthenticated] = useState(null);
useEffect(() => {
isAuthenticated().then((bool) => setAuthenticated(bool));
}, []);
return (
<Route
{...rest}
render={(props) => {
if (authenticated === null) return '...loading';
return authenticated ? <Component {...props} /> : <Redirect to="/login" />;
}}
/>
);
};
const UnauthenticatedRoute = ({ component: Component, ...rest }) => {
const [authenticated, setAuthenticated] = useState(null);
useEffect(() => {
isAuthenticated().then((bool) => setAuthenticated(bool));
}, []);
return (
<Route
{...rest}
render={(props) => {
if (authenticated === null) return '...loading';
return !authenticated ? <Component {...props} /> : <Redirect to="/" />;
}}
/>
);
};
export { AuthenticatedRoute, UnauthenticatedRoute };
我认为问题是Switch
组件需要某些类型的子组件,而您给它传递了一个不同的组件类型AuthenticatedRoute
,它可能无法处理。您可以将组件转换为只返回Route
元素的渲染函数,从而使Switch
仅包含路由,而不是创建新的组件类型。
const renderAuthenticatedRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
isAuthenticated()
? <Component {...props} />
: <Redirect to='/login' />
)} />
);
const renderUnauthenticatedRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
!isAuthenticated()
? <Component {...props} />
: <Redirect to='/' />
)} />
);
class App extends Component {
render() {
return (
<HashRouter>
<React.Suspense fallback={loading()}>
<Switch>
{
renderUnauthenticatedRoute({
exact: true,
path: "/login",
name: "Login Page",
component: Login
})
}
<Route exact path="/register" name="Register Page" component={Register} />
<Route exact path="/404" name="Page 404" component={Page404} />
<Route exact path="/500" name="Page 500" component={Page500} />
{
renderAuthenticatedRoute({
path: "/",
name: "Home",
component: DefaultLayout
})
}
</Switch>
</React.Suspense>
</HashRouter>
);
}
}