Question about react class component setState

46 views Asked by At

I don't understand this part of the code:

this.setState({ usernameValid, errorMsg }, this.validateForm);

If we are updating usernameValid, errorMsg in the state, what does this.validateForm do? Because we are writing this outside the object of setState.

My code:

class StandardForm extends Component {
      state = {
        username: "",
        usernameValid: false,
        email: "",
        emailValid: false,
        password: "",
        passwordValid: false,
        passwordConfirm: "",
        passwordConfirmValid: false,
        formValid: false,
        errorMsg: {},
      };

  validateForm = () =>{
    let { usernameValid, emailValid, passwordValid, passwordConfirmValid} = this.state;
    this.setState({
      formValid: usernameValid && emailValid && passwordValid && passwordConfirmValid
    })
  }

  validateUsername = () => {
    const { username } = this.state;
    let usernameValid = true;
    let errorMsg = { ...this.state.errorMsg };

    if (username.length < 6 || username.length > 16) {
      usernameValid = false;
      errorMsg.username = "Username should be between 6 and 15 characters";
    }
    this.setState({ usernameValid, errorMsg }, this.validateForm);
  };

  validateEmail = () => {
    const { email } = this.state;
    let emailValid = true;
    let errorMsg = { ...this.state.errorMsg };

    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      emailValid = false;
      errorMsg.email = "Invalid email format";
    }

    this.setState({ emailValid, errorMsg }, this.validateForm);
  };

  validatePassword = () =>{
    const { password } = this.state;
    let passwordValid = true;
    let errorMsg = {...this.state.errorMsg}

    if(password.length < 8){
    let passwordValid = false;
      errorMsg.password = "Password should have at least 8 characters"
    }

    this.state({passwordValid, errorMsg})
  }

  confirmPassword  = () =>{
    const { confirmPassword, password } = this.state.confirmPassword
    let passwordConfirmValid = true; 
    let errorMsg = {...this.state.errorMsg}

    if(password !== confirmPassword){
    let passwordConfirmValid = false; 
        errorMsg.passwordConfirm = "Password do not match"
    }

    this.state({passwordConfirmValid, errorMsg})
    
  }
1

There are 1 answers

0
Drew Reese On BEST ANSWER

Class-based component's setState lifecycle function can take a second argument callback function that is called after the state is updated.

setState

setState(updater, [callback])

It was commonly used to do something simple like log the updated state.

this.setState({ value }, () => console.log('new value', this.state.value);

I think generally it should be avoided and if you need to issue any side-effects like validating form data then a regular component lifecycle method should be used. componentDidUpdate handles updated state or props.

From the docs

The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.

In your case with this.setState({ usernameValid, errorMsg }, this.validateForm); the validateForm function reference is passed as a callback and is invoked after state is updated.