【发布时间】:2016-08-10 01:29:27
【问题描述】:
我正在使用 react、redux、react-router 和更高阶的组件。我有一些用户需要登录才能查看的受保护路线,我已将它们包装在一个更高阶的组件中,我将尝试提供尽可能清晰的上下文,请耐心等待。这是我的高阶组件(HOC):
import React from 'react';
import {connect} from 'react-redux';
import { browserHistory } from 'react-router';
export function requireAuthentication(Component, redirect) {
class AuthenticatedComponent extends React.Component {
componentWillMount() {
this.checkAuth();
}
componentWillReceiveProps(nextProps) {
this.checkAuth();
}
checkAuth() {
if (!this.props.isAuthenticated) {
browserHistory.push(redirect);
}
}
render() {
console.log('requireAuthentication render');
return (
<div>
{this.props.isAuthenticated === true
? <Component {...this.props}/>
: null
}
</div>
)
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.loggedIn
});
return connect(mapStateToProps)(AuthenticatedComponent);
}
HOC 会检查 redux 存储以查看用户是否已登录,并且它能够执行此操作,因为返回的 Auth 组件已连接到 redux 存储。
这就是我在路由中使用 HOC 与 react 路由器的方式:
import React, { Component } from 'react';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import Nav from './nav';
import MainBody from './main-body';
import Login from './login';
import Signup from '../containers/signup';
import Dashboard from './dashboard';
import { requireAuthentication } from './require-authentication';
export default class Everything extends Component {
render() {
return (
<div>
<a className="iconav-brand intelliagg-logo-container" href="/">
<span className="iconav-brand-icon intelliagg">Deep-Light</span>
</a>
<Router history={browserHistory}>
<Route path='/' component={Login} >
</Route>
<Route path='/main' component={MainBody}>
<Route path='/dashboard' component={ requireAuthentication(Dashboard, '/') } />
<Route path='/signup' component={Signup} />
</Route>
</Router>
</div>
);
}
}
我导入 HOC 函数并将受保护的路由传递给 HOC,在本例中为 Dashboard。如果用户未登录并尝试访问此视图,他们将被重定向到登录页面。
当用户启动登录时,操作创建者使用用户提供的用户名和密码向服务器发出请求,我有一个减速器,它使用isAuthenticated: true 的标志更新状态:
import { browserHistory } from 'react-router';
export default function(state = false, action) {
let newState;
switch (action.type) {
case 'LOGGED_IN':
newState = action.payload.data.login_status;
return newState;
break;
default:
return state;
}
}
我的减速器:
import { combineReducers } from 'redux';
import formFields from './reducer_form-fields';
import hintReducer from './reducer_hint-reducer';
import errorMessage from './reducer_error-message-submission';
import loggedIn from './reducer_logged-in';
import isAuthenticated from './reducer_isAuthenticated';
const rootReducer = combineReducers({
formInput: formFields,
hint: hintReducer,
errorMessage,
loggedIn,
isAuthenticated
});
export default rootReducer;
所以,我的问题是 HOC 组件总是检查 isAuthenticated 标志,如果设置为 false(这是默认设置),它会将用户重定向到登录页面。由于登录请求需要一些时间并且状态会更新,这意味着用户将始终被重定向到登录页面,因为检查是在客户端立即从 HOC 到 redux 存储的。
如何根据服务器的响应进行检查并相应地重定向用户?有没有办法延迟从 HOC 检查 store 中的 redux 值?
【问题讨论】:
-
React Router 有一个异步认证流程示例:github.com/reactjs/react-router/blob/master/examples/…
标签: javascript authentication reactjs react-router redux