2015-12-31 14 views
5

Ho configurato un'applicazione React utilizzando react-router che si autentica con Firebase.Come si passa lo stato del componente di livello superiore a Routes utilizzando react-router?

Ho questo funzionamento ma ora desidero essere in grado di gestire lo stato dell'utente connesso (auth) dal componente principale App e farlo passare ai componenti figlio invece di dover interrogare lo stato di autenticazione in ogni componente.

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Router, Route, Link, browserHistory } from 'react-router'; 
import { createHistory } from 'history'; 

/* 
    Firebase 
*/ 
import Auth from './modules/Auth'; 
import Helpers from './modules/Helpers'; 

// Auth.unauth(); 
/* 
    Import app modules 
*/ 
import LogIn from './modules/LogIn'; 
import LogOut from './modules/LogOut'; 
import NotFound from './modules/NotFound'; 
import Register from './modules/Register'; 
import Dashboard from './modules/Dashboard'; 
import ResetPassword from './modules/ResetPassword'; 
import ChangePassword from './modules/ChangePassword'; 
import MyAccount from './modules/MyAccount'; 


const App = React.createClass({ 

    getInitialState: function() { 
    return { 
     loggedIn: Auth.getAuth(), 
     userType: null 
    } 
    }, 

    setUserLevel: function(authData) { 
    if(authData){ 
     Auth.child('users/'+authData.uid+'/user_level').once('value', 
     (snapshot) => { 
      this.setState({ userType: Helpers.getUserType(snapshot.val()) }) 
     }, 
     (error) => { 
      this.setState({ 
      userType: Helpers.getUserType(0), 
      error: error 
      }); 
     } 
    ); 
    } 
    }, 

    updateAuth: function(loggedIn) { 
    // console.log('Updating Auth'); 

    this.setUserLevel(loggedIn); 

    this.setState({ 
     loggedIn: loggedIn 
    }) 
    }, 

    componentWillMount: function() { 
    Auth.onAuth(this.updateAuth); 
    }, 

    render: function() { 

    var regButton = (this.state.loggedIn) ? null : (<Link className="Navigation__link" to="register">Register</Link>); 
    var accountButton = (this.state.loggedIn) ? (<Link className="Navigation__link" to="account">My Account</Link>) : null; 

    return (
    <div> 
     <nav className="Navigation"> 
     {this.state.loggedIn ? (
      <Link className="Navigation__link" to="/logout">Log out</Link> 
     ) : (
      <Link className="Navigation__link" to="/login">Sign in</Link> 
     )} 
     {regButton} 
     {accountButton} 
     <Link className="Navigation__link" to="dashboard">Dashboard</Link> 
     </nav> 
     <div> 
     {this.props.children} 
     </div> 
    </div>); 
    } 
}) 


function requireAuth(nextState, replaceState) { 
    if (!Auth.getAuth()) 
    replaceState({ nextPathname: nextState.location.pathname }, '/login') 
} 

function notWhenLoggedIn(nextState, replaceState) { 
    if (Auth.getAuth()) 
    replaceState({ nextPathname: nextState.location.pathname }, '/dashboard') 
} 

var routes = (
    <Router history={createHistory()}> 
    <Route path="/" component={App}> 
     <Route path="/login" component={LogIn} onEnter={notWhenLoggedIn} /> 
     <Route path="/logout" component={LogOut} onEnter={requireAuth} /> 
     <Route path="/register" component={Register} onEnter={notWhenLoggedIn} /> 
     <Route path="/resetpassword" component={ResetPassword} onEnter={notWhenLoggedIn} /> 
     <Route path="/change-password" component={ChangePassword} onEnter={requireAuth} /> 
     <Route path="/dashboard" component={Dashboard} onEnter={requireAuth} /> 
     <Route path="/account" component={MyAccount} onEnter={requireAuth} /> 
     <Route path="*" component={NotFound} /> 
    </Route> 
    </Router> 
) 

ReactDOM.render(routes, document.querySelector('#main')); 

ora ho venire bloccato come non riesco a trovare un modo per tramandare la loggedin state del componente App giù come proprietà sui componenti figlio.

Ciò è possibile anche con react-router?

risposta

3

Il modo migliore che conosco come utilizzare the React.Children utility. Ecco un veloce Codepen per vedere il concetto in azione. http://codepen.io/anon/pen/RrKbjZ

Quindi il codice nella funzione render() del componente App nell'esempio sarà simile a questo.

render: function() { 

    var regButton = (this.state.loggedIn) ? null : (<Link className="Navigation__link" to="register">Register</Link>); 
    var accountButton = (this.state.loggedIn) ? (<Link className="Navigation__link" to="account">My Account</Link>) : null; 
    var childrenWithProps = React.Children.map(this.props.children, (Child, i) => { 
    return React.cloneElement(Child, { 
     loggedIn: this.state.loggedIn 
    }); 
    }); 

    return (
    <div> 
     <nav className="Navigation"> 
     { 
      this.state.loggedIn ? 
      (<Link className="Navigation__link" to="/logout">Log out</Link>) : 
      (<Link className="Navigation__link" to="/login">Sign in</Link>) 
     } 
     {regButton} 
     {accountButton} 
     <Link className="Navigation__link" to="dashboard">Dashboard</Link> 
     </nav> 
     <div> 
     {childrenWithProps} 
     </div> 
    </div> 
); 
} 
+0

Grazie Brandon! Questo è esattamente ciò di cui ho bisogno. Perfezionare! –

0

Ho già lo stesso problema. Questo problema può essere d'aiuto.

https://github.com/rackt/react-router/issues/1857

Tuttavia, questo metodo per il passaggio di parametro non è raccomandare, soprattutto quando si sta costruendo un grande app.

Raccomando alcuni gestori di stato per js, ad esempio "Redux".

Problemi correlati