2015-12-31 40 views
5

我已經使用react-router設置了一個使用Firebase進行身份驗證的React應用。如何將頂級組件狀態傳遞給使用react-router的路由?

我有這個工作,但我現在想要能夠從主App組件管理登錄用戶(身份驗證)的狀態,並將其傳遞給子組件,而不必查詢身份驗證狀態在每個組件中。

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

我現在來卡住,因爲我無法找到一個方式來傳遞下來的loggedIn stateApp組件下來,對孩子組件的屬性。

這是甚至可能與react-router

回答

3

我知道如何使用the React.Children utility的最佳方式。這裏有一個快速的Codepen來看看這個概念的實際應用。 http://codepen.io/anon/pen/RrKbjZ

因此,您示例中App組件的render()函數中的代碼看起來像這樣。

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

謝謝布蘭登!這正是我需要的。完善! –

相關問題