我相信这是一个非常简单的问题,但我不习惯 Async/callback 的世界。
我制作了 PrivateRoute
以保护我的资源不被未经身份验证的用户拍摄。如果我只检查存储中的 token
。它通常会推送到资源。但它不包括过时的 token
。然后我让它拍摄以在继续之前与后端进行验证。
问题:
axios
调用返回正确的值,但页面不会将经过身份验证的用户推送到正确的资源页面
console.log
显示 1 then
并停留在登录页面
App.js
const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
<Route
{...otherProps}
render={props => (
isAuthorized() ? (<Component {...props} />) :
(
<Redirect to={
{
pathname: '/',
state: {from: props.location},
}
}
/>
)
)}
/>
);
function verifyToken(isAuthenticated){
if (isAuthenticated) {
axios.post(`${BACKEND_URL}/api-token-verify/`, {
token: getAuthToken()
}).then((res) => {
console.log('then');
return true;
})
.catch((err) => {
console.log('err');
return false;
});
} else {
console.log('ahaha');
return false;
}
}
// Deal with an ordinary outdated token. Hacked one will be handle on individual component
function hasToken() {
const token = localStorage.getItem('authToken');
const isAuthenticated = !((token === undefined) | (token === null));
return verifyToken(isAuthenticated);
}
class App extends Component {
render() {
return (
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route exact path='/' component={Login}/>
<PrivateRoute exact path='/simulator/' isAuthorized={hasToken} component={Simulator}/>
</Switch>
</BrowserRouter>
</Provider>
)
}
}
export default App;
问题:
我怎样才能让它像顺序一样运行?
答案:
感谢 m0meni
他的回答和评论解决了我的问题。这是我基于他的回答的解决方案。我决定把我的解决方案放在这里,因为将来我可能会忘记它。
我制作了新的 Component
并将其命名为 Container
。因为我不能把 redux
放在这个级别。
class App extends Component {
render() {
return (
<Provider store={store}>
<Container/>
</Provider>
)
}
}
Container.js
import React, {Component, Fragment} from 'react';
import {BrowserRouter, Redirect, Route, Switch} from 'react-router-dom';
import Simulator from "../../simulators/components/Simulators";
import Login from "../../frontpage/components/login";
import {connect} from 'react-redux';
import {CHECK_TOKEN} from "../../constants";
const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
<Route
{...otherProps}
render={props => (
isAuthorized() ? (<Component {...props} />) :
(
<Redirect to={
{
pathname: '/',
state: {from: props.location},
}
}
/>
)
)}
/>
);
// Deal with an ordinary outdated token. Hacked one will be handle on individual component
function hasToken() {
const token = localStorage.getItem('authToken');
return !((token === undefined) | (token === null));
}
class Container extends Component {
/*
* In order to do redux staff and not to mess up with top most <App/>
* Container has been created to contain them all
*
* */
constructor(props) {
super(props);
this.props.validateToken();
}
render() {
console.log(this.props);
const {isAuthenticated, wrapper} = this.props;
console.log(typeof this.props.wrapper);
if((typeof this.props.wrapper) === 'function') {
console.log('this is function');
return (
<Fragment>
<BrowserRouter>
<Switch>
<Route exact path='/' component={Login}/>
<PrivateRoute exact path='/simulator/' isAuthorized={this.props.wrapper} component={Simulator}/>
</Switch>
</BrowserRouter>
</Fragment>
)
}else{
console.log('wrapper is not a function');
console.log(typeof this.props.wrapper);
return null;
}
}
}
const mapStateToProps = ({verifyTokenReducer}, ownProps) => {
return verifyTokenReducer
};
const validateToken = () => {
return {
type: CHECK_TOKEN,
payload: undefined
}
};
export default connect(mapStateToProps, {validateToken})(Container);
reducers.js
import {GOOD_TOKEN, INVALID_TOKEN} from "../constants";
function immediateReturnTrue(){
return true;
}
function immediateReturnFalse(){
return false;
}
export const VerifyTokenReducer = (state = {}, action) => {
switch (action.type) {
case GOOD_TOKEN:
return {
isAuthenticated: true,
wrapper: immediateReturnTrue
};
case INVALID_TOKEN:
return {
isAuthenticated: false,
wrapper: immediateReturnFalse
};
default:
return state;
}
};
最佳答案
这里的关键见解是 verifyToken
将永远返回 true
因为 if 分支不返回任何内容,而 else 分支返回 错误
。 return true
在你的 promise 中是在 .then
的回调中,这意味着 return true
不适用于函数 verifyToken
,而是.then
里面的匿名函数。
为了解决这个问题,您需要从 verifyToken
函数返回 promise ,并在 PrivateRoute
组件中将其作为 promise 处理。现在,您的 render prop 将 promise 视为立即可用的值而不是 promise。 (你没有在任何地方使用 .then
)
render={props => (
isAuthorized() ? (<Component {...props} />) :
(
<Redirect to={
{
pathname: '/',
state: {from: props.location},
}
}
/>
)
)}
关于javascript - 在将历史推送到路由器之前验证 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50567273/