UNPKG

react-form-validator-hook

Version:
172 lines (160 loc) 7.27 kB
import React, {useState} from "react"; const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/i; const useValidator = (state, config) => { const [values, setValues] = useState(state); const [errors, setErrors] = useState({}); const [passwordErrors, setPasswordErrors] = useState({ minLength: !config.password, number: !config.password.rules.number || false, upperCase: !config.password.rules.upperCase || false, lowerCase: !config.password.rules.lowerCase || false, specialChar: !config.password.rules.specialChar || false }); const handleValueChange = (name, value) => { setValues({...values, [name]: value}); validate(name, value); } const handleBlur = (name) => { validate(name, values[name]); } const validateOnSubmit = (event) => { event.preventDefault(); const errors = Object.keys(config).reduce((acc, name) => { const value = values[name]; const error = validate(name, value); return {...acc, [name]: error}; }, {}); setErrors(errors); } const validate = (name, value) => { const rules = config[name].rules; const errorsArray = []; if (rules.required && !value) { errorsArray.push(rules.required.message); } if (rules.pattern && !rules.pattern.value.test(value)) { errorsArray.push(rules.pattern.message); } if (rules.minLength && value.length < rules.minLength) { errorsArray.push(rules.minLength.message); } if (rules.maxLength && value.length > rules.maxLength) { errorsArray.push(rules.maxLength.message); } if (rules.min && value < rules.min) { errorsArray.push(rules.min.message); } if (rules.max && value > rules.max) { errorsArray.push(rules.max.message); } if (rules.email && !emailRegex.test(value)) { errorsArray.push(rules.email.message); } if (rules.confirm && value !== values[rules.confirm.field]) { errorsArray.push(rules.confirm.message); } if (rules.password) { const newPasswordErrors = { minLength: value.length >= rules.minLengthPassword, number: rules.number ? /[0-9]/.test(value) : true, upperCase: rules.upperCase ? /[A-Z]/.test(value) : true, lowerCase: rules.lowerCase ? /[a-z]/.test(value) : true, specialChar: rules.specialChar ? /[^A-Za-z0-9]/.test(value) : true }; setPasswordErrors(newPasswordErrors); if (!Object.values(newPasswordErrors).every((value) => value)) { errorsArray.push(rules.error.message); } } setErrors({...errors, [name]: errorsArray}); return errorsArray; } const PasswordValidationComponent = ({validIcon = 'ok'}) => { return ( <div className={"password-validation"}> <div className={"password-validation-wrapper"}> <div className={"password-validation__item"}> <div className={"password-validation__item__icon"}> {passwordErrors.minLength && validIcon} </div> <div className={`password-validation__item__text ${passwordErrors.minLength && ' valid'}`}> {config.password.rules.minLengthPassword.message} </div> </div> { config.password.rules.number && ( <div className={"password-validation__item"}> <div className={"password-validation__item__icon"}> {passwordErrors.number && validIcon} </div> <div className={`password-validation__item__text ${passwordErrors.number && ' valid'}`}> {config.password.rules.number.message} </div> </div> ) } { config.password.rules.upperCase && ( <div className={"password-validation__item"}> <div className={"password-validation__item__icon"}> {passwordErrors.upperCase && validIcon} </div> <div className={`password-validation__item__text ${passwordErrors.upperCase && ' valid'}`}> {config.password.rules.upperCase.message} </div> </div> ) } { config.password.rules.lowerCase && ( <div className={"password-validation__item"}> <div className={"password-validation__item__icon"}> {passwordErrors.lowerCase && validIcon} </div> <div className={`password-validation__item__text ${passwordErrors.lowerCase && ' valid'}`}> {config.password.rules.lowerCase.message} </div> </div> ) } { config.password.rules.specialChar && ( <div className={"password-validation__item"}> <div className={"password-validation__item__icon"}> {passwordErrors.specialChar && validIcon} </div> <div className={`password-validation__item__text ${passwordErrors.specialChar && ' valid'}`}> {config.password.rules.specialChar.message} </div> </div> ) } </div> </div> ) } const ErrorComponent = ({name}) => { return ( errors[name] && errors[name].length > 0 && ( <div className={"form-error"}> {errors[name].map((error, index) => ( <div key={index} className={"form-error__item"}> {error} </div> ))} </div> ) ) } return { values, errors, handleValueChange, handleBlur, validateOnSubmit, PasswordValidationComponent, ErrorComponent } } export default useValidator;