如何将只有 1 个额外嵌套状态的状态应用到 MongoDB

How can I apply a state with only 1extra nested state to MongoDB

我试图在对密码进行哈希处理时将输入值获取到 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);```
  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);

查看 了解有关嵌套状态更改的更多信息。