[英]render() fucntion not working properly in react
I am using the MERN stack for developing a website.我正在使用 MERN 堆栈来开发网站。 I used passport.js for local authentication.
我使用 passport.js 进行本地身份验证。 The user logins through a login form on
'/login'
on the frontend.用户通过前端
'/login'
上的登录表单登录。 Once the user clicks on the submit button I prevent its default behaviour and send an axios post request at '/login'
on the backend.一旦用户单击提交按钮,我将阻止其默认行为并在后端的
'/login'
处发送 axios 发布请求。 Once the user is authenticated I send the user to '/products'
on the frontend.用户通过身份验证后,我将用户发送到前端
'/products'
。 To know if the user is authenticated or not, I send an axios get request at '/login'
at the backend in the compoundDidMount()
function which sets the state property loggedIn
to true
if user is authenticated, else false
. To know if the user is authenticated or not, I send an axios get request at
'/login'
at the backend in the compoundDidMount()
function which sets the state property loggedIn
to true
if user is authenticated, else false
. If I once again visit '/login'
route on the frontend I should be redirected to '/products'
on the frontend without rendering the code in else
statement (login form) based on the code in the render()
funtion.如果我再次访问前端
'/login'
路由,我应该被重定向到前端'/products'
,而不需要根据render()
函数中的代码在else
语句(登录表单)中呈现代码。 But first, the code in the else
statement (login form) is getting rendered for a fraction of a second and then it's rendering the component on '/products'
.但首先,
else
语句(登录表单)中的代码会在几分之一秒内呈现,然后它会在'/products'
上呈现组件。 Why is this happening?为什么会这样? I don't want the login form to be rendered once I am logged in, on visiting the
'/login'
route on the frontend.我不希望在登录后在访问前端的
'/login'
路由时呈现登录表单。 Here is my code.这是我的代码。
login.js
(Login component) login.js
(登录组件)
import React, { Component } from 'react';
import {Redirect} from 'react-router-dom';
import axios from 'axios';
class Login extends Component {
state = {
email: "",
password: "",
loggedIn: false
}
handleLogin = event => {
event.preventDefault();
const data = {
email: this.state.email,
password: this.state.password
};
axios.post('/login', data)
.then(response => {
// console.log("response status code: ", response.status);
if(response.status === 200) {
// this.setState({loggedIn: true});
this.props.history.push('/products');
}
})
.catch(error => console.log('error is :', error));
}
handleChange = event => {
const property = event.target.name,
value = event.target.value;
this.setState({[property]: value});
}
componentDidMount() {
this.getLoggedInStatus();
}
getLoggedInStatus = () => {
axios.get('/login')
.then(response => {
console.log("response.data is: ", response.data.loggedIn);
this.setState({loggedIn: response.data.loggedIn});
// if(response.data.loggedIn)
// this.props.history.push('/products');
})
.catch(error => console.log("error is : ", error));
// return loggedIn;
}
render() {
// this.getLoggedInStatus();
// console.log("loggedIn is: ", this.state.loggedIn);
if(this.state.loggedIn) {
console.log('Working');
return <Redirect to="/products" />
}
else {
console.log('not working');
return (
<div className="container d-flex justify-content-center mt-5">
<form className="w-50 mt-2" action="/login" method="POST" onSubmit={this.handleLogin}>
<div className="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" name="email" onChange={this.handleChange} id="exampleInputEmail1" aria-describedby="emailHelp" required/>
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" className="form-control" name="password" onChange={this.handleChange} id="exampleInputPassword1" required/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
);
}
}
}
export default Login;
backend code后端代码
router.get('/login', (request, response) => {
response.json({loggedIn: request.isAuthenticated()});
});
router.post('/login', passport.authenticate('local'), (request, response) => {
if(request.isAuthenticated())
// response.json('successful login');
response.status(200).send({message: 'successful login'});
else {
console.log('Not authenticated');
response.status(404).send({message: 'unsuccessful login'});
}
});
You may want to use isLoading
state and show a spinner while the request is in process.您可能希望使用
isLoading
state 并在请求处理时显示微调器。
state = {
email: "",
password: "",
loggedIn: false
idLoading: false
}
...
getLoggedInStatus = () => {
this.setState({ isLoading: true });
axios.get('/login')
.then(response => {
console.log("response.data is: ", response.data.loggedIn);
this.setState({loggedIn: response.data.loggedIn, isLoading: false});
// if(response.data.loggedIn)
// this.props.history.push('/products');
})
.catch(error => console.log("error is : ", error));
// return loggedIn;
}
...
render() {
// this.getLoggedInStatus();
// console.log("loggedIn is: ", this.state.loggedIn);
if(this.state.loggedIn) {
console.log('Working');
return <Redirect to="/products" />
}
else {
if (this.state.isLoading) {
<div>Loading...</div>
}
return (
<div className="container d-flex justify-content-center mt-5">
<form className="w-50 mt-2" action="/login" method="POST" onSubmit={this.handleLogin}>
<div className="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" name="email" onChange={this.handleChange} id="exampleInputEmail1" aria-describedby="emailHelp" required/>
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" className="form-control" name="password" onChange={this.handleChange} id="exampleInputPassword1" required/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
);
}
}
React component life-cycle methods are called in the following sequence: React 组件生命周期方法按以下顺序调用:
Constructor -> componentWillMount -> render -> componentDidMount构造函数 -> componentWillMount -> 渲染 -> componentDidMount
Every time when you go to login page a NEW instance of your Login
component gets created.每次当您 go 登录页面时,都会创建一个新的
Login
组件实例。 Your "implicit" constructor initializes a new instance with state.loggedIn
to false
by您的“隐式”构造函数使用
state.loggedIn
将新实例初始化为false
state = {
email: "",
password: "",
loggedIn: false
}
This causes your render function to show login form and call componentDidMount
which sends a request to the backend.这会导致您的渲染 function 显示登录表单并调用向后端发送请求的
componentDidMount
。 While your component is waiting for a response from the backend - login form is shown on the screen.当您的组件正在等待来自后端的响应时 - 登录表单会显示在屏幕上。 Once response comes in - you set
state.loggedIn
to true which causes another render
call and this time your component redirects to a products
page.一旦响应进来 - 您将
state.loggedIn
设置为 true ,这会导致另一个render
调用,这一次您的组件将重定向到products
页面。
In order to fix your problem you need to move loggedIn
property from component state level to application state level by using something like redux or any other approach to manage front-end application state. In order to fix your problem you need to move
loggedIn
property from component state level to application state level by using something like redux or any other approach to manage front-end application state.
Add an extra property (ie loading) to your state object to track if the login should render or not (and perhaps adding a loading component).添加一个额外的属性(即加载)到您的 state object 以跟踪登录是否应该呈现(并且可能添加一个加载组件)。 See code comment as well.
另请参阅代码注释。
// Your component state
state = {
email: "",
password: "",
loggedIn: false,
loading: true // default state
};
// Your getLoggedInStatus code
getLoggedInStatus = () => {
axios.get('/login')
.then(response => {
console.log("response.data is: ", response.data.loggedIn);
this.setState({loggedIn: response.data.loggedIn, loading: false}); // update loading state to false
})
.catch(error => console.log("error is : ", error));
// return loggedIn;
}
// Your render code
render() {
// this.getLoggedInStatus();
// console.log("loggedIn is: ", this.state.loggedIn);
if(this.state.loggedIn) {
console.log('Working');
return <Redirect to="/products" />
}
else {
if(this.state.loading) {
return(<div> Loading...</div>); // Have something more fancy here
} else {
return (
<div className="container d-flex justify-content-center mt-5">
<form className="w-50 mt-2" action="/login" method="POST" onSubmit={this.handleLogin}>
<div className="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" name="email" onChange={this.handleChange} id="exampleInputEmail1" aria-describedby="emailHelp" required/>
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" className="form-control" name="password" onChange={this.handleChange} id="exampleInputPassword1" required/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.