我尝试在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。 谢谢。
答案 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。