三元运算符没有正确使用 useState
Ternary operator not using the useState correctly
我正在尝试根据状态和从 API 服务器获得的响应来更新 header 组件,但由于某种原因,我更新后的状态出现了某种类型的错误看不懂。
如果用户名和密码正确,当我的 API 服务器响应时,我在浏览器上得到 console.log(response.data) 属性(用户名、密码、令牌) ).我可以登录并且令牌保存在本地 session... 太棒了!但是,当我尝试使用空白 username/password 或任何不正确的数据登录时,我的状态评估为真,因此 HeaderLoggedIn 组件激活(不遵循三元运算符规则集)/我的服务器响应 console.log( 'Incorrect username / password.');但 HeaderLoggedIn 仍然激活。
我的 useState(),最初设置为 Boolean(sessionStorage.getItem('movieappToken')。所以如果没有保存令牌,它是 false,因此它应该是 useState(false) - 渲染HeaderLoggedOut 组件。
我做错了什么?谢谢
主要Header.js组件:
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import HeaderLoggedOut from './HeaderLoggedOut';
import HeaderLoggedIn from './HeaderLoggedIn';
function Header() {
const [loggedIn, setLoggedIn] = useState(
Boolean(sessionStorage.getItem('movieappToken'))
);
return (
<header className="header-bar bg-primary mb-3">
<div className="container d-flex flex-column flex-md-row align-items-center p-3">
<h4 className="my-0 mr-md-auto font-weight-normal">
<Link to="/" className="text-white">
ComplexApp
</Link>
</h4>
**//here's the problem**
{loggedIn ? (
<HeaderLoggedIn setLoggedIn={setLoggedIn} />
) : (
<HeaderLoggedOut setLoggedIn={setLoggedIn} />
)}
</div>
</header>
);
}
export default Header;
HeaderLoggedIn.js分量:
import React, { useEffect } from 'react';
function HeaderLoggedIn(props) {
function handleLogout() {
props.setLoggedIn(false);
sessionStorage.removeItem('movieappToken');
sessionStorage.removeItem('movieappUsername');
}
return (
<div className="flex-row my-3 my-md-0">
<a href="#" className="text-white mr-2 header-search-icon">
<i className="fas fa-search"></i>
</a>
<span className="mr-2 header-chat-icon text-white">
<i className="fas fa-comment"></i>
<span className="chat-count-badge text-white"> </span>
</span>
<a href="#" className="mr-2">
<img
className="small-header-avatar"
src={sessionStorage.getItem('complexappAvatar')}
/>
</a>
<a className="btn btn-sm btn-success mr-2" href="/create-post">
Create Post
</a>
<button onClick={handleLogout} className="btn btn-sm btn-secondary">
Sign Out
</button>
</div>
);
}
export default HeaderLoggedIn;
和HeaderLoggedOut.js组件 - 从API服务器
获取数据的组件
import React, { useEffect, useState } from 'react';
import Axios from 'axios';
function HeaderLoggedOut(props) {
const [username, setUsername] = useState();
const [password, setPassword] = useState();
async function handleSubmit(e) {
e.preventDefault();
try {
const response = await Axios.post('http://localhost:4000/login', {
username,
password,
});
if (response.data) {
console.log(response.data);
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
} else {
console.log('Incorrect username / password.');
}
} catch (e) {
console.log('There was a problem.');
}
}
return (
<form onSubmit={handleSubmit} className="mb-0 pt-2 pt-md-0">
<div className="row align-items-center">
<div className="col-md mr-0 pr-md-0 mb-3 mb-md-0">
<input
onChange={(e) => setUsername(e.target.value)}
name="username"
className="form-control form-control-sm input-dark"
type="text"
placeholder="Username"
autoComplete="off"
/>
</div>
<div className="col-md mr-0 pr-md-0 mb-3 mb-md-0">
<input
onChange={(e) => setPassword(e.target.value)}
name="password"
className="form-control form-control-sm input-dark"
type="password"
placeholder="Password"
/>
</div>
<div className="col-md-auto">
<button className="btn btn-success btn-sm">Sign In</button>
</div>
</div>
</form>
);
}
export default HeaderLoggedOut;
API 服务器 userController.js
const User = require('../models/User');
//
exports.login = function (req, res) {
let user = new User(req.body);
user
.login()
.then(function (result) {
res.send(result);
})
.catch(function (error) {
res.send(error);
});
};
API 服务器 User.js
const usersCollection = require('../db').collection('users');
const bcrypt = require('bcryptjs');
const validator = require('validator');
let User = function (data) {
this.data = data;
this.errors = [];
};
User.prototype.cleanUp = function () {
if (typeof this.data.username != 'string') {
this.data.username = '';
}
if (typeof this.data.email != 'string') {
this.data.email = '';
}
if (typeof this.data.password != 'string') {
this.data.password = '';
}
// get rid of any bogus properties
this.data = {
username: this.data.username.trim().toLowerCase(),
email: this.data.email.trim().toLowerCase(),
password: this.data.password,
token: `58158188ji4j1ij42jio4j1ji41oji14i${this.data.username}`,
};
};
User.prototype.validate = function () {
if (this.data.username == '') {
this.errors.push('You must provide a username');
}
if (
this.data.username != '' &&
!validator.isAlphanumeric(this.data.username)
) {
this.errors.push('Username can only contain letters and numbers');
}
if (!validator.isEmail(this.data.email)) {
this.errors.push('You must provide a valid email address');
}
if (this.data.password == '') {
this.errors.push('You must provide a password');
}
if (this.data.password.length > 0 && this.data.password.length < 7) {
this.errors.push('Password must be at atleast 7 characters');
}
if (this.data.password.length > 25) {
this.errors.push('Password cannot exceed 25 characters');
}
if (this.data.username.length > 0 && this.data.username.length < 3) {
this.errors.push('Username must be at atleast 3 characters');
}
if (this.data.username.length > 15) {
this.errors.push('Username cannot exceed 15 characters');
}
};
User.prototype.register = function () {
// Step #1: Validate user data
this.cleanUp();
this.validate();
// Step #2: Only if there are no validation errors
// then save the user data into a database
if (!this.errors.length) {
// hash user password
let salt = bcrypt.genSaltSync(10);
this.data.password = bcrypt.hashSync(this.data.password, salt);
usersCollection.insertOne(this.data);
}
};
User.prototype.login = function () {
return new Promise((resolve, reject) => {
this.cleanUp();
usersCollection
.findOne({ username: this.data.username })
.then((attemptedUser) => {
if (
attemptedUser &&
bcrypt.compareSync(this.data.password, attemptedUser.password)
) {
resolve(this.data);
} else {
reject('invalid username/password');
}
})
.catch(function () {
reject('Please try again later!');
});
});
};
module.exports = User;
当收到“不正确的 username/password”响应时,您没有设置 loggedIn
,因此 loggedIn
保持最初的状态。您可以将其设置为 false
if (response.data) {
console.log(response.data);
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
} else {
props.setLoggedIn(false);
console.log('Incorrect username / password.');
} catch (e) {
props.setLoggedIn(false);
console.log('There was a problem.');
}
无论您的服务器响应 this.data
、invalid username/password
或 Please try again later!
,它实际上只是响应一个字符串或一个对象。所以会一直进入第一个判断
if (response.data) {
console.log(response.data);
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
}
我觉得你可以再加一个属性比如code
来帮助你判断
if (response.data) {
console.log(response.data);
if (response.data.code === 200) {
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
} else {
props.setLoggedIn(false);
}
}
我正在尝试根据状态和从 API 服务器获得的响应来更新 header 组件,但由于某种原因,我更新后的状态出现了某种类型的错误看不懂。
如果用户名和密码正确,当我的 API 服务器响应时,我在浏览器上得到 console.log(response.data) 属性(用户名、密码、令牌) ).我可以登录并且令牌保存在本地 session... 太棒了!但是,当我尝试使用空白 username/password 或任何不正确的数据登录时,我的状态评估为真,因此 HeaderLoggedIn 组件激活(不遵循三元运算符规则集)/我的服务器响应 console.log( 'Incorrect username / password.');但 HeaderLoggedIn 仍然激活。
我的 useState(),最初设置为 Boolean(sessionStorage.getItem('movieappToken')。所以如果没有保存令牌,它是 false,因此它应该是 useState(false) - 渲染HeaderLoggedOut 组件。
我做错了什么?谢谢
主要Header.js组件:
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import HeaderLoggedOut from './HeaderLoggedOut';
import HeaderLoggedIn from './HeaderLoggedIn';
function Header() {
const [loggedIn, setLoggedIn] = useState(
Boolean(sessionStorage.getItem('movieappToken'))
);
return (
<header className="header-bar bg-primary mb-3">
<div className="container d-flex flex-column flex-md-row align-items-center p-3">
<h4 className="my-0 mr-md-auto font-weight-normal">
<Link to="/" className="text-white">
ComplexApp
</Link>
</h4>
**//here's the problem**
{loggedIn ? (
<HeaderLoggedIn setLoggedIn={setLoggedIn} />
) : (
<HeaderLoggedOut setLoggedIn={setLoggedIn} />
)}
</div>
</header>
);
}
export default Header;
HeaderLoggedIn.js分量:
import React, { useEffect } from 'react';
function HeaderLoggedIn(props) {
function handleLogout() {
props.setLoggedIn(false);
sessionStorage.removeItem('movieappToken');
sessionStorage.removeItem('movieappUsername');
}
return (
<div className="flex-row my-3 my-md-0">
<a href="#" className="text-white mr-2 header-search-icon">
<i className="fas fa-search"></i>
</a>
<span className="mr-2 header-chat-icon text-white">
<i className="fas fa-comment"></i>
<span className="chat-count-badge text-white"> </span>
</span>
<a href="#" className="mr-2">
<img
className="small-header-avatar"
src={sessionStorage.getItem('complexappAvatar')}
/>
</a>
<a className="btn btn-sm btn-success mr-2" href="/create-post">
Create Post
</a>
<button onClick={handleLogout} className="btn btn-sm btn-secondary">
Sign Out
</button>
</div>
);
}
export default HeaderLoggedIn;
和HeaderLoggedOut.js组件 - 从API服务器
获取数据的组件import React, { useEffect, useState } from 'react';
import Axios from 'axios';
function HeaderLoggedOut(props) {
const [username, setUsername] = useState();
const [password, setPassword] = useState();
async function handleSubmit(e) {
e.preventDefault();
try {
const response = await Axios.post('http://localhost:4000/login', {
username,
password,
});
if (response.data) {
console.log(response.data);
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
} else {
console.log('Incorrect username / password.');
}
} catch (e) {
console.log('There was a problem.');
}
}
return (
<form onSubmit={handleSubmit} className="mb-0 pt-2 pt-md-0">
<div className="row align-items-center">
<div className="col-md mr-0 pr-md-0 mb-3 mb-md-0">
<input
onChange={(e) => setUsername(e.target.value)}
name="username"
className="form-control form-control-sm input-dark"
type="text"
placeholder="Username"
autoComplete="off"
/>
</div>
<div className="col-md mr-0 pr-md-0 mb-3 mb-md-0">
<input
onChange={(e) => setPassword(e.target.value)}
name="password"
className="form-control form-control-sm input-dark"
type="password"
placeholder="Password"
/>
</div>
<div className="col-md-auto">
<button className="btn btn-success btn-sm">Sign In</button>
</div>
</div>
</form>
);
}
export default HeaderLoggedOut;
API 服务器 userController.js
const User = require('../models/User');
//
exports.login = function (req, res) {
let user = new User(req.body);
user
.login()
.then(function (result) {
res.send(result);
})
.catch(function (error) {
res.send(error);
});
};
API 服务器 User.js
const usersCollection = require('../db').collection('users');
const bcrypt = require('bcryptjs');
const validator = require('validator');
let User = function (data) {
this.data = data;
this.errors = [];
};
User.prototype.cleanUp = function () {
if (typeof this.data.username != 'string') {
this.data.username = '';
}
if (typeof this.data.email != 'string') {
this.data.email = '';
}
if (typeof this.data.password != 'string') {
this.data.password = '';
}
// get rid of any bogus properties
this.data = {
username: this.data.username.trim().toLowerCase(),
email: this.data.email.trim().toLowerCase(),
password: this.data.password,
token: `58158188ji4j1ij42jio4j1ji41oji14i${this.data.username}`,
};
};
User.prototype.validate = function () {
if (this.data.username == '') {
this.errors.push('You must provide a username');
}
if (
this.data.username != '' &&
!validator.isAlphanumeric(this.data.username)
) {
this.errors.push('Username can only contain letters and numbers');
}
if (!validator.isEmail(this.data.email)) {
this.errors.push('You must provide a valid email address');
}
if (this.data.password == '') {
this.errors.push('You must provide a password');
}
if (this.data.password.length > 0 && this.data.password.length < 7) {
this.errors.push('Password must be at atleast 7 characters');
}
if (this.data.password.length > 25) {
this.errors.push('Password cannot exceed 25 characters');
}
if (this.data.username.length > 0 && this.data.username.length < 3) {
this.errors.push('Username must be at atleast 3 characters');
}
if (this.data.username.length > 15) {
this.errors.push('Username cannot exceed 15 characters');
}
};
User.prototype.register = function () {
// Step #1: Validate user data
this.cleanUp();
this.validate();
// Step #2: Only if there are no validation errors
// then save the user data into a database
if (!this.errors.length) {
// hash user password
let salt = bcrypt.genSaltSync(10);
this.data.password = bcrypt.hashSync(this.data.password, salt);
usersCollection.insertOne(this.data);
}
};
User.prototype.login = function () {
return new Promise((resolve, reject) => {
this.cleanUp();
usersCollection
.findOne({ username: this.data.username })
.then((attemptedUser) => {
if (
attemptedUser &&
bcrypt.compareSync(this.data.password, attemptedUser.password)
) {
resolve(this.data);
} else {
reject('invalid username/password');
}
})
.catch(function () {
reject('Please try again later!');
});
});
};
module.exports = User;
当收到“不正确的 username/password”响应时,您没有设置 loggedIn
,因此 loggedIn
保持最初的状态。您可以将其设置为 false
if (response.data) {
console.log(response.data);
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
} else {
props.setLoggedIn(false);
console.log('Incorrect username / password.');
} catch (e) {
props.setLoggedIn(false);
console.log('There was a problem.');
}
无论您的服务器响应 this.data
、invalid username/password
或 Please try again later!
,它实际上只是响应一个字符串或一个对象。所以会一直进入第一个判断
if (response.data) {
console.log(response.data);
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
}
我觉得你可以再加一个属性比如code
来帮助你判断
if (response.data) {
console.log(response.data);
if (response.data.code === 200) {
sessionStorage.setItem('movieappToken', response.data.token);
sessionStorage.setItem('movieappUsername', response.data.username);
props.setLoggedIn(true);
} else {
props.setLoggedIn(false);
}
}