9

Piszę React aplikację js (v15.3) używając reagować-routera (v2.8.1) i ES6 składni. Nie mogę uzyskać kodu routera, aby przechwycić wszystkie przejścia między stronami, aby sprawdzić, czy użytkownik musi się najpierw zalogować.Sprawdź, czy Zalogowany - React Router App ES6

Moja najwyższym poziomie renderowanie metoda jest bardzo prosta (aplikacja jest trywialne, jak również):

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

wszystkich próbek na kodzie internetowej użycie ES5 lub starsze wersje reagują-Router (starsza niż wersja 2) , i moje różne próby z mixins (przestarzałe) i willTransitionTo (nigdy nie zostanie wywołany) zawiodły.

Jak skonfigurować globalną funkcję przechwytywania, aby zmusić użytkowników do uwierzytelnienia przed lądowaniem na żądanej stronie?

+0

Podałem odpowiedź na podobne pytanie tutaj, może być przydatne. http://stackoverflow.com/a/39098876/6060774 – alexi2

Odpowiedz

1

Ta wersja zwrotnego onEnter końcu pracował reakcji routerem (v2.8)

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

Związek co wyjaśnia różnice reakcji routera, przekierowania pomiędzy vs V1 V2 here. Odpowiednia sekcja cytowany poniżej:

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

Pełna Listing poniżej (reagują-routera wersji 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

Każda trasa ma hak onEnter, który jest wywoływany przed rozpoczęciem przejścia trasy. Obsługa haka onEnter z niestandardową funkcją requireAuth.

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

Próbka wymagajAuth jest pokazana poniżej. Jeśli użytkownik jest uwierzytelniony, przejdź przez next(). W innym przypadku zastąp ścieżkę przez/login i przejście przez next(). Login jest również przekazywany do bieżącej ścieżki, więc po zakończeniu logowania użytkownik zostaje przekierowany na ścieżkę, na którą pierwotnie się ubiegał.

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

To prawie działa. requireAuth jest wywoływany poprawnie, ale wywołanie to replace ({pathname: ...); zawiesza się – DataMania

+0

Zapomniałem wstawić następną() po zamianie(). – vijayst

+0

Funkcja next() nie została zdefiniowana, ale twoja odpowiedź postawiła mnie na właściwej ścieżce – DataMania

1

W v4 po prostu utworzyć komponent trasy, która sprawdza czy jest uwierzytelniony i zastosowania zwróć następne komponenty i oczywiście następnym komponentem mogą być inne trasy.

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