2017-07-08 110 views
0

我嘗試在React中實現登錄頁面。我有一個包含2個輸入字段(ID和密碼)和一個提交按鈕的登錄組件。這個按鈕是Material-Ui按鈕組件。該按鈕有一個onClick方法,用於檢查ID和密碼是否正確。如果是這樣,它必須路由到另一個組件。React-router v4路由點擊按鈕

class Connexion extends React.Component { 
constructor(props) { 
    super(props); 
    this.state = { 
     identifiant: '', 
     password: '', 
     errorMessage: '' 
    }; 

    this.checkIdentifiantAndPassaword = this.checkIdentifiantAndPassword.bind(this); 
    this.handleIdentifiantChange = this.handleIdentifiantChange.bind(this); 
    this.handlePasswordChange = this.handlePasswordChange.bind(this); 
} 
handleIdentifiantChange(e) { 
    this.setState({ 
     identifiant: e.target.value 
    }); 
} 

handlePasswordChange(e) { 
    this.setState({ 
     password: e.target.value 
    }); 
} 
checkIdentifiantAndPassword(e) { 
    let { identifiant, password } = this.state; 
    if (!identifiant) { 
     console.log('check identifiant'); 
     this.setState({ 
      errorMessage: 'Identifiant vide ou incorrect.' 
     }); 
     return; 
    } 
    if (!password) { 
     this.setState({ 
      errorMessage: 'Mot de passe vide ou incorrect.' 
     }); 
     return; 
    } 
    console.log(this.props); 
    this.props.onLogin(true); 
    console.log('Succés'); 
} 
render() { 
    let { errorMessage } = this.state; 
    return (
     <Paper elevation={4} > 
      <Typography type="display2" className="text-center header_title">Connexion</Typography> 
      <div className="row content_container"> 
       <div className="small-4 small-centered columns"> 
        <Typography type="body2" className="loginError">{errorMessage}</Typography> 
        <form> 
         <TextField required value={this.state.identifiant} onChange={this.handleIdentifiantChange} label="Identifiant" type="text" className="txtField" marginForm /> 
         <TextField required value={this.state.password} onChange={this.handlePasswordChange} label="Mot de passe" type="password" className="txtField" marginForm /> 
         <Button raised color="primary" className=" btn" onClick={this.checkIdentifiantAndPassword}>Se connecter</Button> 
        </form> 
       </div> 
      </div> 
     </Paper> 
    ); 
} 

};

我的問題是,我不知道如何通過onClick處理程序重定向到另一個組件。我嘗試了很多解決方案,如在下面一個NavLink包裹按鈕組件:

<NavLink to="/new" ><Button raised color="primary" className=" btn" onClick={this.checkIdentifiantAndPassword}>Se connecter</Button></NavLink> 

,但我在checkIdentifiantAndPassword方法的第一線得到一個錯誤:

Cannot read property 'state' of null 

我知道,我可以刪除按鈕組件,並且只使用NavLink並添加按鈕成分T的所有類NavLink,但我不喜歡這種解決方法。

難道有人有我如何才能做到這一點的想法。我正在使用React-router v4。 謝謝。

回答

2

您可以使用<Redirect/>從 '反應路由器-DOM'。

在文檔他們解釋如何使用(加上專用線)。見https://reacttraining.com/react-router/web/example/auth-workflow

我想也許你可以做某事像這樣:

this.state = { 
    ...., 
    doRedirect: false 
} 

..... 

checkIdentifiantAndPassword(e) { 
    ..... 
    this.setState({ 
    doRedirect: true 
    }); 
} 

..... 

render() { 
    if (this.state.doRedirect) { 
    <Redirect to={/*Your next route*/}/> 
    } 
    ..... 
} 
+0

謝謝恩裏克。我將下面的整個解決方案發布給其他人。 – Alee

0

謝謝恩裏克你的迴應和鏈接。這很有用。 這是我對那些試圖與反應路線V4管理公共和私人途徑整體解決方案。我有2個私人組件,1個公共組件(Connexion),它是連接組件和包含所有這些組件的主要組件。

Connexion組件是一個ID,密碼字段和一個提交按鈕,用於檢查連接是否有效。 如果是,則將用戶路由到專用組件。我還定義了2個其他組件PublicRoute和PrivateRoute。 PrivateRoute檢查用戶是否有效。如果是,則路由到適當的組件。

主要成分

class Main extends React.Component { 
constructor(props) { 
    super(props); 
    this.state = { 
     login: false 
    } 
    super(props); 

    this.handleLogin = this.handleLogin.bind(this); 
    this.handleDeconnexion = this.handleDeconnexion.bind(this);; 
} 
handleDeconnexion(value) { 
    this.setState({ 
     login: value 
    }) 
} 
handleLogin(isAuthenticated) { 
    console.log(isAuthenticated); 
    this.setState(
     { 
      login: isAuthenticated 
     } 
    ); 
} 
render() { 
    let { login } = this.state; 
    return (
     <HashRouter> 
      <div> 
       <Nav isLoggedIn={login} deconnecter={this.handleDeconnexion} /> 
       <div className="row main_container"> 
        <div className="columns medium-10 small-centered"> 
         <PublicRoute exact path="/" component={Connexion} onLogin={this.handleLogin} /> 
         <PrivateRoute isAuthenticated={login} path="/new" component={Nouveau} /> 
         <PrivateRoute isAuthenticated={login} path="/suivi" component={SuiviCas} /> 
        </div> 
       </div> 
      </div> 
     </HashRouter> 
    ); 
} 
} 

聯接部件

class Connexion extends React.Component { 
constructor(props) { 
    super(props); 
    this.state = { 
     identifiant: '', 
     password: '', 
     errorMessage: '', 
     doRedirect: false 
    }; 

    this.handleIdentifiantChange = this.handleIdentifiantChange.bind(this); 
    this.handlePasswordChange = this.handlePasswordChange.bind(this); 
    this.handleLogin = this.handleLogin.bind(this); 
} 

handleIdentifiantChange(e) { 
    this.setState({ 
     identifiant: e.target.value 
    }); 
} 

handlePasswordChange(e) { 
    this.setState({ 
     password: e.target.value 
    }); 
} 
handleLogin(e) { 
    let { identifiant, password } = this.state; 
    if (!identifiant) { 
     this.setState({ 
      errorMessage: 'Identifiant vide ou incorrect.' 
     }); 
     return; 
    } 
    if (!password) { 
     this.setState({ 
      errorMessage: 'Mot de passe vide ou incorrect.' 
     }); 
     return; 
    } 
    this.setState({ 
     doRedirect: true 
    }); 
    this.props.onLogin(true); 
} 
render() { 
    const { from } = this.props.location.state || { from: { pathname: '/thecomponent_you_want_to_redirect_after_login'} 
    let{ doRedirect, errorMessage } = this.state; 
    if (doRedirect) { 
     return (
      <Redirect to={from} /> 
     ) 
    } 
    return (
     <Paper elevation={4} > 
      <Typography type="display2" className="text-center header_title">Connexion</Typography> 
      <div className="row content_container"> 
       <div className="small-4 small-centered columns"> 
        <Typography type="body2" className="loginError">{errorMessage}</Typography> 
        <form> 
         <TextField required value={this.state.identifiant} onChange={this.handleIdentifiantChange} label="Identifiant" type="text" className="txtField" marginForm /> 
         <TextField required value={this.state.password} onChange={this.handlePasswordChange} label="Mot de passe" type="password" className="txtField" marginForm /> 
         <Button raised color="primary" className=" btn" onClick={this.handleLogin}>Se connecter</Button> 
        </form> 
       </div> 
      </div> 
     </Paper> 
    ); 
} 
} 

PrivateRoute組分如果檢查用戶被認證並重定向到相應的路由。如果不是,則路由到Connexion組件。

const PrivateRoute = ({ component: Component, isAuthenticated, ...rest }) => (
<Route {...rest} render={props => (
    isAuthenticated ? (
     <Component {...props} /> 
    ) : (
      <Redirect to={{ 
       pathname: '/', 
       state: { from: props.location } 
      }} /> 
     ) 
)} /> 
); 

PublicRoute部件

const PublicRoute = ({ component: Component, onLogin, ...rest }) => (
<Route {...rest} render={props => (

    <Component onLogin={onLogin} {...props} /> 
)} /> 
); 

這裏是一個有用的YouTube鏈路說明反應路由器v4和一些差異與V2:React router v4