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})
}
Class-based component's setState
lifecycle function can take a second argument callback function that is called after the state is updated.
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 oncesetState
is completed and the component is re-rendered. Generally we recommend usingcomponentDidUpdate()
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.