2016-03-22 6 views
2

Ich versuche, die auth-flow example aus der react-router -repo zu implementieren, aber ich bin in Probleme für meine Usecase, die ich nicht als ein ReactJS Anfänger groke.Wie implementiere ich loginabhängige Pfade mit react-router, wenn sich der Login-Status im Component-Status befindet?

Mein Login-Status basiert auf der Existenz eines CSRF-Cookie, so habe ich eine Methode in meiner App, die die CSRF-Cookie abruft und speichert seinen Wert in Zustand:

@autobind 
class App extends React.Component { 
    constructor() { 
    super(); 

    this.state = { 
     csrfToken : '', 
     log : {} 
    } 
    } 

setCSRFToken() { 
    this.state = { csrfToken : cookie.load('csrf') }; 
    this.setState({ csrfToken : this.state.csrfToken }); 
} 

loggedIn() { 
    return !!this.state.csrfToken 
} 

Da ich nur möchte, dass meine Komponenten sehen, wenn ich angemeldet bin, versuche ich loggedIn nach den Weg in meine Routen zu ändern() mit onEnter = {} requireAuth:

function requireAuth(nextState, replace) { 
    if (!App.loggedIn()) { 
    console.log('No csrfToken found, asking for login') 
    replace({ 
     pathname: '/login', 
     state: {nextPathname: nextState.location.pathname } 
    }) 
    } 
} 

render((
    <Router history={hashHistory}> 
    <Route path="/" component={App} onEnter={requireAuth}> 
     <IndexRoute component={Home}/> 
     <Route path="/hello" component={Hello}/> 
    </Route> 
    </Router> 

), document.querySelector('#main')) 

App.loggedIn() ist funktioniert nicht th obwohl es keine öffentliche Funktion ist. Gemäß dieser answer hat eine öffentliche Funktion in ReactJS keinen Zugriff auf den internen Zustand, wie von der Architektur von React beabsichtigt, so dass es nicht helfen würde, es mit statischen zu implementieren.

Ich könnte wahrscheinlich weitermachen und den Login-Status im lokalen Speicher speichern, aber ich frage mich, ob es einen anderen Ansatz gibt, dies in ReactJS zu lösen.

Antwort

1

I Einbuchzustand in Store habe die Einrichtung (wie Flux schon sagt) und in Routen:

const UserStore = require("./stores/UserStore.js"); 

let is_user_logged_in = !!UserStore.getToken(); 

UserStore.addChangeListener(() => { 
    is_user_logged_in = !!UserStore.getToken(); 
}); 

function requireAuth(nextState, replaceState) { 
    if (!is_user_logged_in) { 
     replaceState({nextPathname: 'login'}, ''); 
    } 
} 

const routes = (
    <Route path="/" component={Layout}> 
     <IndexRoute component={Home}/> 
     <Route path="login" component={Login}/> 
     <Route path="secret" component={Secret} onEnter={requireAuth}/> 
     <Route path="*" component={NotFound}/> 
    </Route> 
); 

module.exports = routes; 

große Werke, baute mehrere Anwendungen mit diesem :)

UserStore.js:

"use strict"; 
const AppDispatcher = require('./../dispatchers/AppDispatcher.js'); 
const EventEmitter = require('eventemitter3'); 
const assign = require('object-assign'); 
const store = require('store'); 
const Api = require('./../helpers/Api.js'); 
const UserActions = require('./../actions/UserActions.js'); 
import { browserHistory } from 'react-router'; 

const UserStore = assign({}, EventEmitter.prototype, { 

    token: null, 
    error: null, 

    setError: function ({error}) { 
     this.error = error; 
    }, 

    getError: function() { 
     return this.error; 
    }, 

    setToken: function ({token}) { 
     this.token = token; 

     if (token !== null) { 
      store.set('token', token); 
     } else { 
      store.remove('token'); 
     } 
    }, 

    getToken: function() { 
     return this.token; 
    }, 

    emitChange: function() { 
     this.emit('USER_CHANGE'); 
    }, 

    addChangeListener: function (cb) { 
     this.on('USER_CHANGE', cb); 
    }, 

    removeChangeListener: function (cb) { 
     this.removeListener('USER_CHANGE', cb); 
    }, 

}); 

AppDispatcher.register(function (action) { 

    switch (action.actionType) { 
     case 'user_login': 
      Api.login({ 
       username: action.data.username, 
       password: action.data.password, 
       cb: function ({error, response}) { 
        if (error !== null) { 
         console.log('#dfd4sf424'); 
         console.log(error); 
         UserActions.logout(); 
        } else { 
         if (response['success'] === false) { 
          UserStore.setError({error: response['error']}); 
          UserStore.emitChange(); 
         } else { 
          UserStore.setError({error: null}); 
          UserStore.setToken({token: response['auth-token']}); 
          UserStore.emitChange(); 
         } 
        } 
       } 
      }); 
      break; 
     case 'user_logout': 
      UserStore.setToken({token: null}); 
      UserStore.setError({error: null}); 
      UserStore.emitChange(); 
      break; 
     case 'user_auto_login': 
      UserStore.setToken({token: action.data.token}); 
      UserStore.setError({error: null}); 
      UserStore.emitChange(); 
      break; 
    } 
}); 

module.exports = UserStore; 
+0

Hrrm, ich hoffte, ich könnte jetzt ohne Flussmittel/Redux tun ... Aber ich werde diesen Ansatz versuchen. Könntest du bitte etwas über das Konzept des Ladens erzählen oder Links hinzufügen, also ist die Antwort umfassender, bevor ich es akzeptiere? Die redux-Dokumentation gibt einen schönen Überblick über das Konzept, denke ich: http://redux.js.org/docs/api/Store.html Die Dokumentation auf reactjs.org ist ziemlich trocken und unzugänglich imho :-( –

+0

reactjs sollte solche Dokumente nicht geben, weil es Sache des Entwicklers ist. Es ist nicht reagieren Sache, nur einfaches Javascript mit einigen Muster namens Fluss. Hinzugefügt meine Benutzer-Shop-Code zu beantworten –

+0

Ja, du hast Recht - wollte nur über die ReactJS- Docs im Allgemeinen denke ich ;-) –

Verwandte Themen