单击按钮

时间:2017-07-08 11:31:29

标签: reactjs react-router

我尝试在React中实现登录页面。我有一个带有2个输入字段(id和密码)和一个提交按钮的登录组件。此按钮是Material-Ui按钮组件。该按钮有一个onClick方法,用于检查id和密码是否正确。如果是这样,它必须路由到另一个组件。

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 并将按钮组件的所有类添加到 NavLink ,但我不喜欢这种解决方法。

有人知道如何实现这一目标。我正在使用React-router v4。 谢谢。

2 个答案:

答案 0 :(得分:2)

您可以使用&#39; react-router-dom&#39;中的<Redirect/>

在文档中,他们解释了如何使用(加上私人路线)。请参阅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*/}/>
  }
  .....
}

答案 1 :(得分:1)

感谢Henrique的回复和链接。这很有用。 对于那些尝试使用 react-route 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>
    );
}
}

Connexion组件

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链接,解释react-router v4以及与v2的一些差异:React router v4