webentwicklung-frage-antwort-db.com.de

Prüfen Sie, ob Sie angemeldet sind - React Router App ES6

Ich schreibe eine React .js-Anwendung (Version 15.3) mit Reakt-Router (Version 2.8.1) und ES6-Syntax. Ich kann den Router-Code nicht abrufen, um alle Übergänge zwischen Seiten abzufangen, um zu prüfen, ob sich der Benutzer zuerst anmelden muss.

Meine Rendering-Methode auf oberster Ebene ist sehr einfach (die App ist auch trivial):

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

Alle Beispiele im Web verwenden ES5-Code oder ältere Versionen von Reakt-Router (älter als Version 2), und meine verschiedenen Versuche mit Mixins (veraltet) und willTransitionTo (werden nie aufgerufen) sind fehlgeschlagen.

Wie kann ich eine globale "Interceptor-Funktion" einrichten, um Benutzer zu zwingen, sich zu authentifizieren, bevor sie auf der angeforderten Seite landen?

13

Diese Version des onEnter-Callbacks funktionierte schließlich für den reag-router (v2.8):

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

Der Link, der die Unterschiede der Reaktorrout-Umleitung zwischen V1 und v2 erklärt, ist hier . Relevanter Abschnitt unten zitiert:

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

Vollständige Code-Liste (Reakt-Router-Version 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>
  );
}
0

Jede Route verfügt über einen onEnter-Hook, der aufgerufen wird, bevor der Routenübergang erfolgt. Behandeln Sie den onEnter-Hook mit einer benutzerdefinierten RequireAuth-Funktion.

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

Ein Beispiel für requestAuth ist unten dargestellt. Wenn der Benutzer authentifiziert ist, wechseln Sie mit next (). Andernfalls ersetzen Sie den Pfadnamen durch/login und den Übergang mit next (). Der Anmeldung wird auch der aktuelle Pfadname übergeben, so dass der Benutzer nach Abschluss der Anmeldung zu dem Pfad umgeleitet wird, für den er ursprünglich angefordert wurde.

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

In Version 4 erstellen Sie einfach eine Routenkomponente, die prüft, ob die Verwendung authentifiziert ist, und gibt die nächsten Komponenten zurück. Natürlich kann die nächste Komponente auch andere Routen sein.

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