我开始在React中学习和练习,我的想法是制作一个登录屏幕,在其中我调用rest api并将用户存储在内存中,登录后将用户重定向到Home。问题是我希望如果用户已登录,则应该无法查看登录屏幕。为此,我将“ isLogged”状态发送到“ login”组件,如果用户具有“ Logged”状态,我想将其重定向。问题在于状态未正确获得:
app.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import './App.css';
import Login from './Pages/Login/Login'
import Logout from './Pages/Logout/Logout'
import Home from './Pages/Home/Home'
export default class App extends Component{
constructor(){
super();
this.state = {
loggedIn: "no-logueado",
user:{},
};
this.handleLogin = this.handleLogin.bind(this);
this.handleLogout = this.handleLogout.bind(this);
this.loggedIn = this.loggedIn.bind(this);
}
handleLogin(data){
this.setState({
loggedIn: "Logueado",
user: data
});
}
handleLogout(){
this.setState({
loggedIn: "no-logueado",
user: {}
});
}
isLoggedin(){
const token = localStorage.getItem("authToken");
if(this.state.loggedIn === "no-logueado" && token){
this.setState({
loggedIn: "Logueado",
user: token
});
}
}
loggedIn(data){
if(data === "Logueado"){
window.location="/home";
}
}
async componentDidMount(){
await this.isLoggedin();
}
render() {
return (
<Router>
<Route exact path="/" render={props => ( <Login {... props} handleLogin={this.handleLogin} loggedIn={this.state.loggedIn}/>)} />
<Route exact path="/logout" render={props => ( <Logout {... props} handleLogout={this.handleLogout}/>)} />
<Route exact path="/home" render={props => (<Home {... props} loggedIn={this.loggedIn} log={this.state.loggedIn}/>)} />
<script src="https://unpkg.com/react/umd/react.production.min.js" crossorigin></script>
<script
src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"
crossorigin></script>
<script
src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
crossorigin></script>
<script>var Alert = ReactBootstrap.Alert;</script>
</Router>
);
}
}
登录
import React, { Component } from 'react'
import Input from './Components/Input/input'
import Label from './Components/Label/Label'
import 'bootstrap/dist/css/bootstrap.min.css';
import './Login.css'
import {Container, Row, Col, Button} from 'react-bootstrap'
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
user:' ',
password:' '
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleSuccessfullAuth = this.handleSuccessfullAuth.bind(this);
}
handleChange(name, value) {
if(name==='username'){
this.setState({user:value});
} else {
this.setState({password:value});
}
}
async handleSubmit(){
const requestOptions = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
email: this.state.user,
password:this.state.password
})
};
const response = await fetch('http://localhost:4000/login', requestOptions);
console.log(response.ok);
if(response.ok){
const res = await response.json();
localStorage.setItem("authToken", res.token)
this.handleSuccessfullAuth(res);
} else {
console.log("token", localStorage.getItem("authToken"))
}
}
handleSuccessfullAuth(data){
this.props.handleLogin(data);
this.props.history.push("/home");
}
componentDidMount(){
console.log(this.props.loggedIn)
}
render(){
return (
<div id="login-background">
<Container>
<Row>
<Col xs={6}>
<Col xs={8} className="back">
<h2 className="tittle-login">¡ Bienvenido !</h2>
<h2 className="tittle-login">{this.props.loggedIn}</h2>
<hr className="hr-design"></hr>
<Label text='Usuario'/>
<Input attribute= {{
id: 'username',
name:'username',
type:'text',
placeholder:'Ingrese su usuario ...',
className:'form-control'
}}
handleChange={this.handleChange}
/>
<Label text='Contraseña'/>
<Input attribute= {{
id: 'password',
name:'password',
type:'password',
placeholder:'Ingrese su contraseña ...',
className:'form-control'
}}
handleChange={this.handleChange}
/><br></br>
<Button variant="primary" size="lg" block onClick={this.handleSubmit}>Iniciar Sesión</Button>{' '}
</Col>
<Col xs={4}>
</Col>
</Col>
<Col>
</Col>
</Row>
</Container>
</div>
)
}
}
当我通过控制台查看状态如何到达“登录”状态时,尽管屏幕使我“登录”,但状态仍为“未登录”。
我认为我需要首先学习一些东西,或者我错过了一些东西,您能帮我吗?
Render "Logueado" but in console i obtain an "No-logueado" status
首页
import React, { Component } from 'react'
import Menu from '../../Components/Menu'
export default class Home extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Menu/>
</div>
)
}
}
答案 0 :(得分:0)
如果用户已登录,则可以使用Redirect
中的'react-router-dom'
组件从登录页面重定向到主页。
只需在render()
函数内添加条件返回。
render() {
if (this.props.loggedIn === STATE_LOGGED_IN) {
return <Redirect path="/home" />;
}
return (
<div id="login-background">
<Container>
...
我还自由地重构了您的组件。我为您提供一些建议。
首先,您可以使用箭头函数代替需要绑定的类方法。箭头函数没有this
关键字,因此不需要绑定。
handleLogin = (data) => {
this.setState({
loggedIn: STATE_LOGGED_IN,
user: data,
});
};
其次,我建议您使用children
呈现的<Route>
形式。它更干净,更容易阅读。
<Router>
<Route exact path="/">
<Login handleLogin={this.handleLogin} loggedIn={this.state.loggedIn} />
</Route>
<Route exact path="/logout">
<Logout handleLogout={this.handleLogout} />
</Route>
<Route exact path="/home">
<Home loggedIn={this.state.loggedIn} />
</Route>
</Router>
您还将注意到,我删除了名为window.location="/home"
的函数。我建议您使用react-router-dom
来更改位置,而不要直接修改window.location
。
最后,我建议您为'Logueado'
和'no-logueado'
字符串使用常量字符串。通过使用const,可以避免错误键入字符串的问题。
export const STATE_LOGGED_IN = 'Logueado';
export const STATE_LOGGED_OUT = 'no-logueado';
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import './App.css';
import Login from './Pages/Login/Login';
import Logout from './Pages/Logout/Logout';
import Home from './Pages/Home/Home';
export const STATE_LOGGED_IN = 'Logueado';
export const STATE_LOGGED_OUT = 'no-logueado';
export default class App extends Component {
constructor() {
super();
this.state = {
loggedIn: STATE_LOGGED_OUT,
user: {},
};
}
componentDidMount() {
this.isLoggedin();
}
handleLogin = (data) => {
this.setState({
loggedIn: STATE_LOGGED_IN,
user: data,
});
};
handleLogout = () => {
this.setState({
loggedIn: STATE_LOGGED_OUT,
user: {},
});
};
isLoggedin = () => {
const token = localStorage.getItem('authToken');
if (this.state.loggedIn === STATE_LOGGED_OUT && token) {
this.setState({
loggedIn: STATE_LOGGED_IN,
user: token,
});
}
};
render() {
return (
<Router>
<Route exact path="/">
<Login handleLogin={this.handleLogin} loggedIn={this.state.loggedIn} />
</Route>
<Route exact path="/logout">
<Logout handleLogout={this.handleLogout} />
</Route>
<Route exact path="/home">
<Home loggedIn={this.state.loggedIn} />
</Route>
</Router>
);
}
}
请注意render方法中的条件返回。
import React, { Component } from 'react';
import Input from './Components/Input/input';
import Label from './Components/Label/Label';
import 'bootstrap/dist/css/bootstrap.min.css';
import './Login.css';
import { Container, Row, Col, Button } from 'react-bootstrap';
import { STATE_LOGGED_IN, STATE_LOGGED_OUT } from '../../App';
import { Redirect } from 'react-router';
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
user: ' ',
password: ' ',
};
}
componentDidMount() {
console.log(this.props.loggedIn);
}
handleChange = (name, value) => {
if (name === 'username') {
this.setState({ user: value });
} else {
this.setState({ password: value });
}
}
async handleSubmit = () => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: this.state.user,
password: this.state.password,
}),
};
const response = await fetch('http://localhost:4000/login', requestOptions);
console.log(response.ok);
if (response.ok) {
const res = await response.json();
localStorage.setItem('authToken', res.token);
this.handleSuccessfullAuth(res);
} else {
console.log('token', localStorage.getItem('authToken'));
}
}
handleSuccessfullAuth = (data) => {
this.props.handleLogin(data);
this.props.history.push('/home');
}
render() {
if (this.props.loggedIn === STATE_LOGGED_IN) {
return <Redirect path="/home" />;
}
return (
<div id="login-background">
<Container>
<Row>
<Col xs={6}>
<Col xs={8} className="back">
<h2 className="tittle-login">¡ Bienvenido !</h2>
<h2 className="tittle-login">{this.props.loggedIn}</h2>
<hr className="hr-design"></hr>
<Label text="Usuario" />
<Input
attribute={{
id: 'username',
name: 'username',
type: 'text',
placeholder: 'Ingrese su usuario ...',
className: 'form-control',
}}
handleChange={this.handleChange}
/>
<Label text="Contraseña" />
<Input
attribute={{
id: 'password',
name: 'password',
type: 'password',
placeholder: 'Ingrese su contraseña ...',
className: 'form-control',
}}
handleChange={this.handleChange}
/>
<br></br>
<Button variant="primary" size="lg" block onClick={this.handleSubmit}>
Iniciar Sesión
</Button>{' '}
</Col>
<Col xs={4}></Col>
</Col>
<Col></Col>
</Row>
</Container>
</div>
);
}
}