9

我寫一個陣營使用反應路由器(v2.8.1)和ES6語法 .js文件的應用程序(v15.3)。我無法獲取路由器代碼來攔截頁面之間的所有轉換,以檢查用戶是否需要先登錄。檢查是否已登錄 - 陣營路由器應用ES6

我頂層渲染方法很簡單(應用程序是微不足道的爲好):

render() 
    { 
     return (
     <Router history={hashHistory}> 
      <Route path="/" component={AppMain}> 
       <Route path="login" component={Login}/> 
       <Route path="logout" component={Logout}/> 
       <Route path="subject" component={SubjectPanel}/> 
       <Route path="all" component={NotesPanel}/> 
      </Route> 
     </Router> 
    ); 
    } 

所有在網絡上使用ES5代碼樣本或老版本的反應,路由器(年齡超過2版) ,而且我用mixin(不建議使用)和willTransitionTo(永遠不會調用)的各種嘗試都失敗了。

如何設置一個全局的「攔截器函數」來強制用戶在登陸他們請求的頁面之前進行身份驗證?

+0

我在這裏提供了一個類似問題的答案,它可能是有用的。 http://stackoverflow.com/a/39098876/6060774 – alexi2

回答

1

這個版本的OnEnter回調終於工作了反應路由器(V2.8):

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

這也解釋了反應路由器VS V2 V1之間的差異重定向是here鏈接。引述有關章節如下:

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' } }) 

完整的代碼下面的清單(反應路由器版本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> 
); 
} 
6

每條路由都有一個onEnter掛鉤,它在路由轉換髮生之前被調用。使用自定義的requireAuth函數處理onEnter鉤子。

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

示例requireAuth如下所示。如果用戶通過身份驗證,則通過next()進行轉換。否則用/ login替換路徑名並通過next()轉換。登錄也傳遞當前路徑名,以便在登錄完成後,用戶被重定向到最初請求的路徑。

function requireAuth(nextState, replace, next) { 
    if (!authenticated) { 
    replace({ 
     pathname: "/login", 
     state: {nextPathname: nextState.location.pathname} 
    }); 
    } 
    next(); 
} 
+0

這幾乎工作。 requireAuth被正確調用,但調用replace({pathname:...);掛起 – DataMania

+0

我忘了把replace()後的下一個()。 – vijayst

+0

next()函數沒有定義,但你的回答讓我走上了正確的軌道 – DataMania

1

在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);