Javascript 检查是否已登录-React路由器应用程序ES6

Javascript 检查是否已登录-React路由器应用程序ES6,javascript,authentication,reactjs,ecmascript-6,react-router,Javascript,Authentication,Reactjs,Ecmascript 6,React Router,我正在使用React路由器(v2.8.1)和ES6语法编写React.js应用程序(v15.3)。我无法获取路由器代码来拦截页面之间的所有转换,以检查用户是否需要先登录 我的顶级渲染方法非常简单(应用程序也很简单): render() { 返回( ); } web上的所有示例都使用ES5代码或旧版本的react router(早于版本2),并且我对Mixin(已弃用)和WillTransitiono(从未调用)的各种尝试都失败了 如何设置全局“拦截器功能”以强制用户在登录他们请求的页面之前进行

我正在使用React路由器(v2.8.1)和ES6语法编写React.js应用程序(v15.3)。我无法获取路由器代码来拦截页面之间的所有转换,以检查用户是否需要先登录

我的顶级渲染方法非常简单(应用程序也很简单):

render()
{
返回(
);
}
web上的所有示例都使用ES5代码或旧版本的react router(早于版本2),并且我对Mixin(已弃用)和WillTransitiono(从未调用)的各种尝试都失败了


如何设置全局“拦截器功能”以强制用户在登录他们请求的页面之前进行身份验证?

每个路由都有一个在路由转换发生之前调用的onEnter hook。使用自定义的requireAuth函数处理onEnter钩子

<Route path="/search" component={Search} onEnter={requireAuth} />

此版本的OneNet回调最终适用于react路由器(v2.8):

解释V1和v2之间路由器重定向差异的链接是。以下引用相关章节:

Likewise, redirecting from an onEnter hook now also uses a location descriptor.

// v1.0.x
(nextState, replaceState) => replaceState(null, '/foo')
(nextState, replaceState) => replaceState(null, '/foo', { the: 'query' })

// v2.0.0
(nextState, replace) => replace('/foo')
(nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } })
下面列出的完整代码(react路由器版本2.8.1):

requireAuth(nextState,
               replace)
{
   if(!this.authenticated()) // pseudocode - SYNCHRONOUS function (cannot be async without extra callback parameter to this function)
     replace('/login');
}

render() {
  return (
     <Router history={hashHistory}>
        <Route path="/" component={AppMain}>
           <Route path="login" component={Login}/>
           <Route path="logout" component={Logout}/>
           <Route path="subject" component={SubjectPanel} onEnter={this.requireAuth}/>
           <Route path="all" component={NotesPanel} onEnter={this.requireAuth}/>
        </Route>
     </Router>
  );
}
requireAuth(下一状态,
替换)
{
if(!this.authenticated())//伪代码-同步函数(如果没有此函数的额外回调参数,则不能是异步的)
替换('/login');
}
render(){
返回(
);
}

在v4中,您只需创建一个路由组件,检查使用是否经过身份验证,并返回下一个组件,当然,下一个组件可以是其他路由

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Route, Redirect } from 'react-router-dom';

import AuthMiddleware from 'modules/middlewares/AuthMiddleware';

class PrivateRoute extends Component {
  static propTypes = {
    component: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool,
    isLoggedIn: PropTypes.func.isRequired,
    isError: PropTypes.bool.isRequired
  };

  static defaultProps = {
    isAuthenticated: false
  };

  constructor(props) {
    super(props);
    if (!props.isAuthenticated) {
      setTimeout(() => {
        props.isLoggedIn();
      }, 5);
    }
  }

  componentWillMount() {
    if (this.props.isAuthenticated) {
      console.log('authenticated');
    } else {
      console.log('not authenticated');
    }
  }
  componentWillUnmount() {}

  render() {
    const { isAuthenticated, component, isError, ...rest } = this.props;
    if (isAuthenticated !== null) {
      return (
        <Route
          {...rest}
          render={props => (
            isAuthenticated ? (
              React.createElement(component, props)
            ) : (
              <Redirect
                to={{
                  pathname: isError ? '/login' : '/welcome',
                  state: { from: props.location }
                }}
              />
            )
          )}
        />
      );
    } return null;
  }

}

const mapStateToProps = (state) => {
  return {
    isAuthenticated: state.auth.isAuthenticated,
    isError: state.auth.isError
  };
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    isLoggedIn: () => AuthMiddleware.isLoggedIn()
  }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute);
import React,{Component}来自'React';
从“道具类型”导入道具类型;
从'react redux'导入{connect};
从“redux”导入{bindActionCreators};
从“react router dom”导入{Route,Redirect};
从“模块/中间件/AuthMiddleware”导入AuthMiddleware;
类PrivateRoute扩展组件{
静态类型={
组件:PropTypes.func.isRequired,
已验证:PropTypes.bool,
isLoggedIn:PropTypes.func.isRequired,
isError:PropTypes.bool.isRequired
};
静态defaultProps={
I验证:错误
};
建造师(道具){
超级(道具);
如果(!props.isAuthenticated){
设置超时(()=>{
props.isLoggedIn();
}, 5);
}
}
组件willmount(){
如果(此.props.isAuthenticated){
console.log('authenticated');
}否则{
console.log(“未验证”);
}
}
componentWillUnmount(){}
render(){
const{isAuthenticated,component,isError,…rest}=this.props;
如果(已验证!==null){
返回(
(
我被认证了(
React.createElement(组件、道具)
) : (
)
)}
/>
);
}返回null;
}
}
常量mapStateToProps=(状态)=>{
返回{
isAuthenticated:state.auth.isAuthenticated,
isError:state.auth.isError
};
};
const mapDispatchToProps=(调度)=>{
返回bindActionCreators({
isLoggedIn:()=>AuthMiddleware.isLoggedIn()
},派遣);
};
导出默认连接(mapStateToProps、mapDispatchToProps)(PrivateRoute);

如果您使用的是react router 4及以上版本,请使用渲染道具和重定向来解决此问题。请参阅:

这不是一个安全的解决方案
您可以尝试在每个需要登录的页面上使用useEffect钩子:

这将使用“react router dom”中的useHistory钩子
您只需在调用它之前对其进行初始化:

const history = useHistory();

如上所述,这不是一个安全的解决方案,但很简单,我在这里提供了一个类似问题的答案,它可能是有用的。这几乎奏效了。requireAuth调用正确,但是调用replace({pathname:…);挂起我忘记在replace()之后放一个next()。next()函数没有定义,但是您的回答让我走上了正确的轨道模块名是什么?
requireAuth(nextState,
               replace)
{
   if(!this.authenticated()) // pseudocode - SYNCHRONOUS function (cannot be async without extra callback parameter to this function)
     replace('/login');
}

render() {
  return (
     <Router history={hashHistory}>
        <Route path="/" component={AppMain}>
           <Route path="login" component={Login}/>
           <Route path="logout" component={Logout}/>
           <Route path="subject" component={SubjectPanel} onEnter={this.requireAuth}/>
           <Route path="all" component={NotesPanel} onEnter={this.requireAuth}/>
        </Route>
     </Router>
  );
}
import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Route, Redirect } from 'react-router-dom';

import AuthMiddleware from 'modules/middlewares/AuthMiddleware';

class PrivateRoute extends Component {
  static propTypes = {
    component: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool,
    isLoggedIn: PropTypes.func.isRequired,
    isError: PropTypes.bool.isRequired
  };

  static defaultProps = {
    isAuthenticated: false
  };

  constructor(props) {
    super(props);
    if (!props.isAuthenticated) {
      setTimeout(() => {
        props.isLoggedIn();
      }, 5);
    }
  }

  componentWillMount() {
    if (this.props.isAuthenticated) {
      console.log('authenticated');
    } else {
      console.log('not authenticated');
    }
  }
  componentWillUnmount() {}

  render() {
    const { isAuthenticated, component, isError, ...rest } = this.props;
    if (isAuthenticated !== null) {
      return (
        <Route
          {...rest}
          render={props => (
            isAuthenticated ? (
              React.createElement(component, props)
            ) : (
              <Redirect
                to={{
                  pathname: isError ? '/login' : '/welcome',
                  state: { from: props.location }
                }}
              />
            )
          )}
        />
      );
    } return null;
  }

}

const mapStateToProps = (state) => {
  return {
    isAuthenticated: state.auth.isAuthenticated,
    isError: state.auth.isError
  };
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    isLoggedIn: () => AuthMiddleware.isLoggedIn()
  }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute);
useEffect(() => {
  const token = localStorage.getItem('token');
  if(!token) {
    history.push('/login');
  }
}
const history = useHistory();