在条件中捕获新的错误状态的问题

时间:2019-05-04 21:25:40

标签: reactjs

晚上好,伙计们,我面临着一个看似简单的问题,对不起我的英语不好。 单击保存按钮时将调用handleSubmit方法,因此三元条件语句检查字段是否在验证中,如果不是,则将其状态更改为true,从而在输入中呈现错误。

初始状态

  nameError: false,
  cpfError: false,
  emailError: false,
  phoneError: false,
  birthdayError: false,
  addressError: false,
  numberError: false,
  districtError: false,
  stateError: false,
  cityError: false,
  cepError: false,

完整方法提交:

handleSubmit = () => {
  this.state.name.length < 4
    ? this.setState({ nameError: true })
    : this.setState({ nameError: false })
  this.state.cpf.length < 14
    ? this.setState({ cpfError: true })
    : this.setState({ cpfError: false })
  this.state.email.length === 0
    ? this.setState({ emailError: true })
    : this.setState({ emailError: false })
  this.state.phone.length < 15
    ? this.setState({ phoneError: true })
    : this.setState({ phoneError: false })
  this.state.birthday.length < 10
    ? this.setState({ birthdayError: true })
    : this.setState({ birthdayError: false })
  this.state.address.length === 0
    ? this.setState({ addressError: true })
    : this.setState({ addressError: false })
  this.state.number.length === 0
    ? this.setState({ numberError: true })
    : this.setState({ numberError: false })
  this.state.district.length === 0
    ? this.setState({ districtError: true })
    : this.setState({ districtError: false })
  this.state.state.length === 0
    ? this.setState({ stateError: true })
    : this.setState({ stateError: false })
  this.state.city.length === 0
    ? this.setState({ cityError: true })
    : this.setState({ cityError: false })
  this.state.cep.length !== 9
    ? this.setState({ cepError: true })
    : this.setState({ cepError: false })

  if (
    !this.state.nameError &&
    !this.state.cpfError &&
    !this.state.emailError &&
    !this.state.phoneError &&
    !this.state.birthdayError &&
    !this.state.addressError &&
    !this.state.numberError &&
    !this.state.districtError &&
    !this.state.stateError &&
    !this.state.cityError &&
    !this.state.cepError
  ) {
    this.props.updateUser({
      name: this.state.name,
      cpf: this.state.cpf,
      email: this.state.email,
      phone: this.state.phone,
      birthday: this.state.birthday,
      address: this.state.address,
      number: this.state.number,
      district: this.state.district,
      complement: this.state.complement,
      state: this.state.state,
      city: this.state.city,
      cep: this.state.cep,
      avatar: this.state.avatar,
    })
  }
}

问题在此处的此处。

在此情况下,条件不会显示先前设置的新状态,如果再次单击“保存”按钮,它将显示新状态。我要去哪里错了?有人可以分享知识。在所有字段都为空的情况下,这种情况很快就会在三元条件中每个人的错误状态都变为true,但是if的状态仍然是旧的,这是因为setstate和异步吗?

if (
  !this.state.nameError &&
  !this.state.cpfError &&
  !this.state.emailError &&
  !this.state.phoneError &&
  !this.state.birthdayError &&
  !this.state.addressError &&
  !this.state.numberError &&
  !this.state.districtError &&
  !this.state.stateError &&
  !this.state.cityError &&
  !this.state.cepError
) {
  this.props.updateUser({
    name: this.state.name,
    cpf: this.state.cpf,
    email: this.state.email,
    phone: this.state.phone,
    birthday: this.state.birthday,
    address: this.state.address,
    number: this.state.number,
    district: this.state.district,
    complement: this.state.complement,
    state: this.state.state,
    city: this.state.city,
    cep: this.state.cep,
    avatar: this.state.avatar,
  })
}

2 个答案:

答案 0 :(得分:1)

是的,您使用this.setState()this.props.updateUser()创建的逻辑是异步的。您想要的是在更新状态后呼叫this.props.updateUser()this.setState()实际上带有一个可选的辅助参数,您可以在状态完成更新后调用它,这正是您所需要的。

让我在这里通过帮助您重组一些代码来帮助您。这也是沙盒:https://codesandbox.io/s/zxpnk301pl

此外,您真的要避免在每次检查输入值时不断更新状态。这可能会导致非常糟糕的性能问题。最好仅执行一项操作即可更新状态。

import React from 'react'
import ReactDOM from 'react-dom'

class App extends React.Component {
  state = {
    name: '',
    cpfr: '',
    email: '',
    phone: '',
    birthday: '',
    address: '',
    number: '',
    district: '',
    state: '',
    city: '',
    cep: '',
    errors: {},
  }

  handleOnChange = event => {
    this.setState({
      [event.target.name]: event.target.value,
    })
  }

  validateAndSubmit = event => {
    event.preventDefault()
    const {
      name,
      cpfr,
      email,
      phone,
      birthday,
      address,
      number,
      district,
      state,
      city,
      cep,
      errors,
    } = this.state
    name.length < 4 ? (errors.name = true) : delete errors.name
    cpfr.length < 14 ? (errors.cpfr = true) : delete errors.cpfr
    email.length === 0 ? (errors.email = true) : delete errors.email
    phone.length < 15 ? (errors.phone = true) : delete errors.phone
    birthday.length < 10 ? (errors.birthday = true) : delete errors.birthday
    address.length === 0 ? (errors.address = true) : delete errors.address
    number.length === 0 ? (errors.number = true) : delete errors.number
    district.length === 0 ? (errors.district = true): delete errors.district
    state.length === 0 ? (errors.state = true) : delete errors.state
    city.length === 0 ? (errors.city = true) : delete errors.city
    cep.length !== 9 ? (errors.cep = true) : delete errors.cep

    this.setState(
      {
        errors: errors,
      },
      () => {
        //check if there are no errors
        if(Object.keys(this.state.errors).length === 0){
          this.props.updateUser({
            name: this.state.name,
            cpf: this.state.cpf,
            email: this.state.email,
            phone: this.state.phone,
            birthday: this.state.birthday,
            address: this.state.address,
            number: this.state.number,
            district: this.state.district,
            complement: this.state.complement,
            state: this.state.state,
            city: this.state.city,
            cep: this.state.cep,
            avatar: this.state.avatar,
          })
        }
      }
    )
  }

  render() {
    return (
      <div>
        <form onSubmit={this.validateAndSubmit}>
          <input
            name="name"
            value={this.state.name}
            onChange={this.handleOnChange}
          />
          <input
            name="cpfr"
            value={this.state.cpfr}
            onChange={this.handleOnChange}
          />
          <input
            name="email"
            value={this.state.email}
            onChange={this.handleOnChange}
          />
          <input
            name="phone"
            value={this.state.phone}
            onChange={this.handleOnChange}
          />
          <input
            name="birthday"
            value={this.state.birthday}
            onChange={this.handleOnChange}
          />
          <input
            name="address"
            value={this.state.address}
            onChange={this.handleOnChange}
          />
          <input
            name="number"
            value={this.state.number}
            onChange={this.handleOnChange}
          />
          <input
            name="district"
            value={this.state.district}
            onChange={this.handleOnChange}
          />
          <input
            name="state"
            value={this.state.state}
            onChange={this.handleOnChange}
          />
          <input
            name="city"
            value={this.state.city}
            onChange={this.handleOnChange}
          />
          <input
            name="cep"
            value={this.state.cep}
            onChange={this.handleOnChange}
          />
          <button>Submit</button>
        </form>
        You have {Object.keys(this.state.errors).length} errors
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))

答案 1 :(得分:1)

问题在于setState是异步的,但是您要在状态完成更新之前检查它。您可以将其重构为一个调用,而不是对每个检查进行多个setState调用,然后在setState回调中进行更新,例如:

// Collect all of your error items
const nameError = this.state.name.length < 4;
const cpfError = this.state.cpf.length < 14;
...

// Set the state with your error values
this.setState({
  nameError,
  cpfError,
  ...
}, () => { // <-- The second parameter of setState is a callback called after it is finished
  if (
    !this.state.nameError &&
    !this.state.cpfError &&
    ...
  ) {
     this.props.updateUser({
       name: this.state.name,
       ...
     });
  }
);