react redux身份验证,取state的问题

前端:react技术栈
后端:express+mongoose

前端的身份验证通过session,进入首页会请求,验证身份,身份信息放在store状态树中的userInfo下面。

当进入/admin 路由下的时候,正常逻辑是取出状态树中的userInfo信息,判断是否为admin,否,则Redirect。

问题:正常的admin登陆后,从页面点击Link可以正常访问到/admin管理界面。但是,当我在/admin页面下刷新的时候,就被Redirect到/首页了。原因是,当我刷新的时候,store状态树重建,包括一些身份验证的异步action发起。在我AdminIndex的render中,直接获取userInfo信息,刚开始获取下来的是空对象,后面才是真实数据。但是,当我获取下来是空的时候就直接Redirect了。

代码如下:

import React, {Component, PropTypes} from 'react'
import PureRenderMixin from 'react-addons-pure-render-mixin'
import {connect} from 'react-redux'
import {actions} from '../../reducers/index'
import {bindActionCreators} from 'redux'
import {
    Redirect
} from 'react-router-dom'
const {user_auth} = actions;
class AdminIndex extends Component {
    constructor(props) {
        super(props);
        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this)
    }

    render() {
        console.info(this.props.userInfo)
        return (
            <div>
                {this.props.isAdmin? <h1>admin管理页面</h1>:<Redirect to='/'/>}
            </div>
        )
    }
}

AdminIndex.defaultProps = {
    isAdmin:false
};

function mapStateToProps(state) {
    return {
        isAdmin: state.globalState.userInfo.userType === 'admin',
        userInfo:state.globalState.userInfo
    }
}

function mapDispatchToProps(dispatch) {
    return {
        user_auth:bindActionCreators(user_auth,dispatch)
    }
}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(AdminIndex)

关键代码也就是:

render() {
        console.info(this.props.userInfo)
        return (
            <div>
                {this.props.isAdmin? <h1>admin管理页面</h1>:<Redirect to='/'/>}
            </div>
        )
    }
    

console内容如下:

clipboard.png

请问该如何处理这个身份验证呢。

ps:在node中,我是分页面服务器和API服务器的,也就是当请求地址为/api的时候我会proxy到另一个服务器,所以在身份验证的时候,貌似API服务器redirect并没有起作用。

然后就想问,对于store中state状态树的异步该如何处理呢?

或者说,目前这个问题,有什么好的解决办法呢?

望大神不啬赐教~

阅读 4.6k
2 个回答

说来也巧,我最近也碰见了这个问题。
基本思路和楼上的差不多,就是进入这个页面先去验证当前状态树的登录标记位,如果不为空,就认为已经登录。如果为空,就去 localStoragetoken,如果取不到token, 直接跳转至登录页面, 取到token, 就去发请求验证token的有效性, 根据返回结果再进行对应操作。
我定义了一个 AuthRoute 的组件去实现上面的逻辑, 大致代码如下所示:
(10.10更新,render 方法返回内容用 Route 包括,不然不能实现 url 参数获取等 route 的api)

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Loader } from 'semantic-ui-react';
import {
    withRouter,
    Route
} from 'react-router-dom';

import { validate } from '../actions/GlobalAction';

class AuthRoute extends Component {
    constructor(props) {
        super(props);
        this.isLogin = false;
    }

    componentWillMount() {
        const token = this.props.token;
        if (token) {
            this.isLogin = true;
        } else {
            const localToken = localStorage.token;
            if (localToken) {
                this.props.dispatch(validate(localToken, this.props.history));
            } else {
                this.props.history.push('/login');
            }
        }
    }

    render() {
        const { token, component, ...rest } = this.props;
        const CustomComponent = component;
        this.isLogin = token !== null;
        return (
            <Route
                {...rest}
                render={props => (
                    this.isLogin ? (
                        <CustomComponent {...props} />
                    ) : (
                        <Loader active inline="centered" />
                    )
                )}
            />
        );
    }
}

AuthRoute.propTypes = {
    dispatch: PropTypes.func.isRequired,
    history: PropTypes.shape().isRequired,
    component: PropTypes.func.isRequired,
    location: PropTypes.shape(),
    token: PropTypes.string
};
AuthRoute.defaultProps = {
    location: {},
    token: null
};

function mapStateToProps(state) {
    return {
        token: state.Global.token
    };
}

export default withRouter(connect(mapStateToProps)(AuthRoute));

然后, 路由配置的时候直接使用 <AuthRoute path="/manager" component={Manager} />.

  1. 缓存
  2. url带参数
    刷新时候,初始化state时候,用上面2个方式获得参数进行初始化state即可。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏