javascript - 使用高阶组件进行身份验证时如何延迟检查 redux 存储

标签 javascript authentication reactjs react-router redux

我正在使用 react、redux、react-router 和高阶组件。我有一些 protected 路由,用户需要登录才能查看,我已将它们包装在高阶组件中,我会尽量提供尽可能清晰的上下文,请耐心等待。这是我的高阶组件 (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 store 以查看用户是否已登录,并且它能够执行此操作,因为返回的 Auth 组件已连接到 redux store。

这就是我在带有 React 路由器的路由中使用 HOC 的方式:

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 函数并将 protected 路由传递给 HOC,在本例中为 Dashboard。如果用户未登录并尝试访问此 View ,他们将被重定向到登录页面。

当用户启动登录时,这是通过一个 Action 创建者完成的,该 Action 创建者使用用户提供的用户名和密码向服务器发出请求,我有一个 reducer,它使用一个标志更新状态 isAuthenticated :真:

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;
  }
}

我的 reducer :

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 检查商店中的 redux 值?

最佳答案

我不同意 Hayo 的观点,因为使用 onEnter 是最好的方法。请参阅此 SO 帖子,了解为什么我认为 HOC 解决方案(就像您使用的那样)是更好的方法:Universal Auth Redux & React Router .

至于您的具体问题,您可以通过将 isAuthenticating bool 值添加到您的 reducer 并在 checkAuth() 函数期间将其传递到您的 HOC 来完成此操作。当它为真时,您可能想要显示一个替代组件,如加载栏/微调器/等,以向用户提供一些反馈。您的 reducer 可以将此 bool 值默认为 true,然后在 LOGGED_IN 上将其设置为 false。您的 reducer 可能看起来像这样:

const initialState = { isAuthenticating: true, isAuthenticated: false };
export default function(state = initialState, action) {
  let newState;
  switch (action.type) {
    case 'LOGGED_IN':
      newState = { isAuthenticating: false, isAuthenticated: action.payload.data.login_status };
      return newState;
    default:
      return state;
  }
}

然后在您的 HOC 的 render() 中,如果 isAuthenticating 为真,您可以返回一个 LoadingComponent 而不是 null。

这与我们刚刚在此 PR 中添加到 redux-auth-wrapper 的功能非常相似 - https://github.com/mjrussell/redux-auth-wrapper/pull/35如果您想将其用于更多引用

关于javascript - 使用高阶组件进行身份验证时如何延迟检查 redux 存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36691796/

相关文章:

javascript - 更新用户权限 Facebook

asp.net - IE 不保存 asp.net 身份验证 token /cookie

reactjs - 如何每 X 秒刷新一次 React-Admin 列表数据?

android - 无法解析模块 `AccessibilityInfo`

Javascript 警报正在打开 PHP 包含文件并且不停留在主页上

javascript - 正则表达式将Javascript中的字符串拆分为多个字符串的逻辑

javascript - js排序时保留选中项

authentication - 使用 Twisted 通过客户端证书身份验证保护 Websockets

c# - 对一个特定端点(.net core)使用不同的授权

reactjs - 将错误响应拦截器放在 redux-axios-middleware 上