I am getting this error when trying to type a password longer than 6 characters in the following react form
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
for each character the user inputs in password/confirm password, I need to validate them.
How can I do this avoiding this infinite loop?
export const Signup: FC<InjectedFormProps<string>> = (props) => {
const {handleSubmit} = props
const {t} = useTranslation()
const [password, setPassword] = useState();
const [confirmPassword, setConfirmPassword] = useState();
const [isValid, setValidity] = useState(false);
const errorMessage = useSelector(getErrorMessage)
const onChangePassword = (event: any) => {
setPassword(event.target.value)
}
const onChangeConfirmPassword = (event: any) => {
setConfirmPassword(event.target.value)
}
const validatePasswords = () => {
if (password && confirmPassword) {
setValidity(password === confirmPassword)
}
}
useEffect(() => {
validatePasswords();
}, [password, confirmPassword, isValid])
const minLength = minLengthPassword(6)
return (
<form onSubmit={handleSubmit}>
<FRow className="full-width">
<FGroup>
<Field validate={minLength} onChange={onChangePassword} name="password" component="input" type="password" placeholder="Password"/>
</FGroup>
</FRow>
<FRow className="full-width">
<FGroup>
<input onChange={onChangeConfirmPassword} name="confirmPassword" type="password" placeholder="Confirm Password"/>
</FGroup>
</FRow>
<FRow>
{isValid ? '' : <Error>{t("auth.lbl_passwords_must_match")}</Error>}
</FRow>
<FullWidthSvgButton disabled={!isValid}>
<span>{t("buttons.btn_sign_up")}</span>
</FullWidthSvgButton>
{errorMessage && (
<Error>{errorMessage}</Error>
)}
</form>
)
}
export const SignupForm = reduxForm<any>({
form: "Signup",
})(Signup)
export default SignupForm
CodePudding user response:
Try to remove isValid
from the dependencies.
useEffect(() => {
validatePasswords();
}, [password, confirmPassword])
You should run your setValidity
only when password
or confirmPassword
changed. If you call it when your isValid
changed - you are getting the infinite loop (because setValidity
changes isValid
)
CodePudding user response:
Please update your hooks like the following.
Wrap validatePasswords
by useCallback
with dependencies of 2 states.
And add this function in dependency of useEffect.
const validatePasswords = useCallback( () => {
if (password && confirmPassword) {
setValidity(password === confirmPassword)
}
}, [password, confirmPassword])
useEffect(() => {
validatePasswords();
}, [validatePasswords])