我正在尝试对我的密码进行哈希处理时将输入值获取到mongoDB。
但是我的方案密码位于一个对象(localProvider)内部。 (这仅用于教育,这是我的老师编写的代码)
{
username: {
type: String,
required: false,
},
email: {
type: String,
required: true,
trim: true,
unique: true,
match: /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
},
localProvider: {
password: {
type: String,
required: false,
},
},
facebookProvider: {
id: { type: String, required: false },
token: { type: String, required: false },
},
published_at: { type: Date, required: false },
deleted_at: { type: Date, required: false },
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
},
{
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
},
);
UserSchema.methods.slugify = function () {
this.slug = slug(this.email);
};
UserSchema.pre('validate', function (next) {
if (!this.slug) {
this.slugify();
}
return next();
});
UserSchema.pre('save', function (next) {
const user = this;
if (!user.isModified('localProvider.password')) return next();// only hash the password if it has been modified (or is new)
try {
return bcrypt.genSalt(config.auth.bcrypt.SALT_WORK_FACTOR, (errSalt, salt) => {
if (errSalt) throw errSalt;
return bcrypt.hash(user.localProvider.password, salt, (errHash, hash) => {
if (errHash) throw errHash;
user.localProvider.password = hash;
return next();
});
});
} catch (error) {
return next(error);
}
});
UserSchema.methods.comparePassword = function (candidatePassword, cb) {
const user = this;
bcrypt.compare(candidatePassword, user.localProvider.password, (err, isMatch) => {
if (err) return cb(err, null);
return cb(null, isMatch);
});
};
UserSchema.virtual('id').get(function () { return this._id; });
UserSchema.plugin(mongoosePaginate);
export default mongoose.model('User', UserSchema);
我已经尝试在register.js中使用onChange传递输入值
[event.target.name]: event.target.value
只有这一行代码仅适用于单个值,而不适用于对象内部。
正如您在方案中所看到的那样,到目前为止,我知道无法将值传递给单个状态值和嵌套状态值。
因此,有解决方案来修复代码,以便我还能将用户名和电子邮件推送到状态,并在1 handleChange中将密码推送到localProvider吗?
来自register.js的代码
class Signup extends Component {
constructor() {
super()
this.state = {
username: '',
email: '',
redirectTo: null,
localProvider:{
password: ''
}
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleInputChange(event, value){
this.setState({
[event.target.name]: event.target.value
})
}
handleChange(el) {
let inputName = el.target.name;
let inputValue = el.target.value;
let statusCopy = Object.assign({}, this.state);
statusCopy.localProvider[inputName].value = inputValue;
this.setState(statusCopy);
}
handleSubmit(event) {
console.log('sign-up handleSubmit, username: ')
console.log(this.state.username)
event.preventDefault()
//request to server to add a new username/password
axios.post('/api/v1/users/', {
...this.state
})
.then(response => {
console.log(response)
if (!response.data.errmsg) {
console.log('successful signup')
this.props.history.push("/");
} else {
console.log('username already taken')
}
}).catch(error => {
console.log('signup error: ')
console.log(error)
})
}
render() {
const { classes } = this.props;
return (
<React.Fragment>
<CssBaseline />
<Paper className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form}>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="name">Name</InputLabel>
<Input name="username" type="text" id="username" autoComplete="username" onChange={this.handleInputChange} />
</FormControl>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="email">Email Address</InputLabel>
<Input id="email" name="email" autoComplete="email" onChange={this.handleInputChange} />
</FormControl>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="password">Password</InputLabel>
<Input type="password" id="password" autoComplete="current-password" onChange={this.handleChange} name="password"/>
</FormControl>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
>
Sign in
</Button>
</form>
</Paper>
</React.Fragment>
)
}
}
export default withStyles(styles)(Signup);```
答案 0 :(得分:1)
handleChange(el) {
let inputName = el.target.name;
let inputValue = el.target.value;
let providerCopy = Object.assign({}, this.state.localProvider); // new
let statusCopy = Object.assign({}, this.state, {localProvider: providerCopy}); //edited
statusCopy.localProvider[inputName].value = inputValue;
this.setState(statusCopy);
}
Object.assign()仅复制到一个级别深,而您需要将复制深度复制到2个级别,因此您可以使用两次或在对象上使用散布运算符。
let nextState = {...this.state, localProvider: {...this.state.localProvider, [el.target.name]: [el.target.value] } };
this.setState(nextState);
请查看here,以获取有关嵌套状态更改的更多信息。