Как я могу применить состояние только с 1 вложенным состоянием к MongoDB - PullRequest
0 голосов
/ 05 июня 2019

Я пытаюсь получить входное значение в 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 Только эта строка кода работает только для отдельных значений, а не внутри объекта. Как вы видели на схеме, насколько я знаю, нет способа передать значение одному значению состояния и вложенному состоянию.

Так есть ли решение для исправления кода, чтобы я мог также передать имя пользователя и адрес электронной почты в состояние и отправить пароль для localProvider в 1 handleChange?

код из моего 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);```

1 Ответ

1 голос
/ 06 июня 2019
  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);

Смотрите здесь для получения дополнительной информации об изменениях вложенного состояния.

...