[英]Trouble updating boolean value with save() using mongoose
所以我遇到了一個有趣的問題,我可以使用前端將 boolean 值更改為 true,但不能恢復為 false。 我的代碼:
updateUser.js(后端)
import express from 'express';
import mongoose from 'mongoose';
import User from '../models/userModel.js';
const app = express();
const uUserRouter = express.Router();
uUserRouter.post('/:id', (req, res) => {
User.findById(req.params.id)
.then(user => {
user.username = req.body.username || user.username;
user.email = req.body.email || user.email;
user.password = req.body.password || user.password;
user.avatar = req.body.avatar || user.avatar;
user.isBanned = req.body.isBanned || user.isBanned;
user.rank = req.body.rank || user.rank;
user.save()
.then(() => res.send('User Updated!'))
.catch(err => res.status(400).send("Update Failed: " + err.message))
})
.catch(err => res.status(404).send('This user cannot be found: ' + err.message))
});
export default uUserRouter;
adminPanel.component.js(前端)
import axios from 'axios';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Button, Container, Table } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const Topic = props => (
<tr>
<td className="tTitle">
{props.topic.title}
</td>
<td className="tDescription">
{props.topic.description}
</td>
<td><Button variant="secondary" onClick={() => { props.deleteTopic(props.topic._id) }}>Delete</Button></td>
</tr>
)
const User = props => (
<tr>
<td className="aPAvatar"><img src={props.user.avatar} height="15%" width="15%" alt="avatar"/></td>
<td>{props.user.username}</td>
<td>{props.user.rank}</td>
<td>{props.user.isBanned ? <Button variant="primary" onClick={() => { props.unBanUser(props.user._id) }}>Unban User</Button> : <Button variant="warning" onClick={() => { props.banUser(props.user._id) }}>Ban User</Button>}</td>
<td><Button variant="secondary" onClick={() => { props.deleteUser(props.user._id) }}>Delete</Button></td>
</tr>
)
class AdminPanel extends Component {
constructor(props) {
super(props);
this.banUser = this.banUser.bind(this);
this.deleteTopic = this.deleteTopic.bind(this);
this.deleteUser = this.deleteUser.bind(this);
this.unBanUser = this.unBanUser.bind(this);
this.state = {
topics: [],
users: []
};
}
componentDidMount() {
function getTopics() {
return axios.get('http://localhost:5000/forum/topics')
}
function getUsers() {
return axios.get('http://localhost:5000/users')
}
Promise.all([getTopics(), getUsers()])
.then((results) => {
const topics = results[0].data;
const users = results[1].data;
this.setState({topics, users}, () => {
console.log(this.state);
});
}).catch((e) => {
console.log('Error: ', e);
});
}
listTopics = () => {
return this.state.topics.map(currenttopic => {
return <Topic topic={currenttopic} deleteTopic={this.deleteTopic} key={currenttopic._id} />
})
}
listUsers = () => {
return this.state.users.map(currentuser => {
return <User user={currentuser} deleteUser={this.deleteUser} banUser={this.banUser} unBanUser={this.unBanUser} key={currentuser._id} />
})
}
banUser(id) {
if (window.confirm('Are you sure you want to ban this user?')) {
axios.post('http://localhost:5000/users/update/'+id, {isBanned: true})
.then(res => {console.log(res.data)})
.catch((e) => {
console.log('Error: ', e)
});
window.alert('User banned successfully');
window.location.reload();
} else {
window.alert('Ban Canceled');
}
}
unBanUser(id) {
axios.post('http://localhost:5000/users/update/'+id, {isBanned: false})
.then(res => {console.log(res.data)});
console.log('test');
window.alert('User Unbanned');
}
deleteTopic(id) {
if (window.confirm('Are you sure you want to delete this topic?')) {
axios.delete('http://localhost:5000/forum/topics/'+id)
.then(res => console.log(res.data));
this.setState({
topics: this.state.topics.filter(el => el._id !== id)
})
window.alert('Topic Deleted');
} else {
window.alert('Deletion Canceled');
}
}
deleteUser(id) {
if (window.confirm('Are you sure you want to delete this user?')) {
axios.delete('http://localhost:5000/users/delete/'+id)
.then(res => console.log(res.data));
this.setState({
users: this.state.users.filter(el => el._id !== id)
})
window.alert('User Deleted')
} else {
window.alert('Deletion Canceled')
}
}
render() {
return (
<Container>
{this.props.isLoggedIn && this.props.rank === 'Admin' ?
<Container>
<div className="userList">
<h3>Users</h3>
<Table>
<thead>
<tr>
<td>Avatar</td>
<td>Username</td>
<td>Rank</td>
<td>Ban Hammer</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
{this.listUsers()}
</tbody>
</Table>
</div>
<div className="topicList">
<h3>Topics</h3>
<Table>
<thead>
<tr>
<td>Title</td>
<td>Discription</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
{this.listTopics()}
</tbody>
</Table>
<Link to="/new-topic">
<Button variant="secondary" className="newTopic">Create a Topic</Button>
</Link>
</div>
</Container>
:
<Container>
<h1>You must be logged in and an Administrator to view this page. <Link to='/'>Return to Home</Link></h1>
</Container>
}
</Container>
)
};
}
const mapSateToProps = state => {
return {
isLoggedIn: state.login.loggedIn,
rank: state.login.user.rank
}
}
export default connect(mapSateToProps)(AdminPanel);
用戶模型.js
import mongoose from 'mongoose';
import bcrypt from 'bcrypt'
const Schema = mongoose.Schema;
const SALT_WORK_FACTOR = 10;
const userSchema = new Schema({
username: {
type: String,
required: true,
trim: true,
/*validate: {
validator: function(username) {User.doesNotExist({ username })},
message: "Username already exists"
},*/
minlength: 5
},
email: {
type: String,
/*validate: {
validator: function(email) {User.doesNotExist({ email })},
message: "Email already exists"
}*/
},
password: {type: String,
required: true,
index: {unique: true} },
avatar: {
type: String,
default: `${process.env.AWSFILESERICE}/pics/defaultPP.png`
},
isBanned: {
type: Boolean,
default: false
},
rank: {
type: String,
default: "Default"
},
joined: {
type: Date
},
topics: [{type: Schema.Types.ObjectId, ref: 'Topics'}],
threads: [{type: Schema.Types.ObjectId, ref: 'Topics.Threads'}],
posts: [{type: Schema.Types.ObjectId, ref: 'Topics.Threads.Posts'}]
}, { timestamps: true});
userSchema.pre('save', function(next) {
const user = this;
if (!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
userSchema.statics.doesNotExist = async function (field) {
return await this.where(field).countDocuments() === 0;
}
userSchema.methods.authenticate = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if (isMatch === true) {
return cb(null, isMatch);
} else {
return cb();
}
})
};
const User = mongoose.model('User', userSchema);
export default User;
(忽略注釋掉的驗證字段,它是一個未完成的實驗:))
更新路線的所有其他帖子(應該是“用戶/更新/#id”)都有效。 即用戶名、密碼、email,甚至isBanned = true。 將其更改回 false 不起作用。 是的,解禁按鈕確實“起作用”,它將請求發送到后端,就像它應該做的那樣,后端將“用戶更新”發送回前端,但數據庫中的 isBanned 值保持不變。 我希望我只是忽略了一些東西,但我閱讀了所有我能解決的問題以及重新閱讀我的代碼......提前感謝您的幫助!
如果您想嚴格使用 boolean 值,此解決方案應該可以工作,
... // Other user schema data
isBanned: String
然后在保存時使用value.toString()
將 boolean 轉換為字符串,因此它保存為包含真/假值的字符串,然后在需要時使用
var originalValue = false; var toSave = originalValue.toString(); console.log(toSave + ", It's a "+typeof toSave); // When needed to check if the user is banned or not // I'll ignore DB things var isBanned = JSON.parse(toSave); console.log(isBanned + ", It's a "+typeof isBanned);
對我來說是最簡單也是最好的解決方案
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.