0.9.0
π Features
Custom input validation errors
It's now possible to specify custom validation errors for invalid inputs. These errors can be retrieved from the form state for rendering purposes.
A validation error can be specified using the existing validate
method. An input is considered invalid if this method returns false, non-empty strings, non-empty objects, non-empty arrays, etc.
<input
{...password({
name: 'password',
validate: (value, values, event) => {
const errors = {};
if (!value) {
errors.required = 'Password is required';
}
if (!STRONG_PASSWORD_REGEX.test(value)) {
errors.weak = 'Password is not strong enough';
}
return errors; // empty objects are not considered errors!
},
})}
/>
When this input is invalid, you'll notice the returned value from the validate method available in the form state under errors.password
.
{
errors: {
// the value of errors.password is determined via the validate method
password: {
weak: 'Password is not strong enough',
required: 'Password is required',
},
}
}
Further reading:
- https://github.com/wsmd/react-use-form-state#custom-input-validation
- https://github.com/wsmd/react-use-form-state#input-options
β¨ Improvements
The input's validate
method gives you access to the change/blur event
It's now possible to access the change/blur event via the validate method. This can helpful if you want to access the underlying DOM node to perform certain checks.
<input
required
pattern={VALID_USERNAME_REGEX}
minLength={4}
text({
name: 'username',
validate: (value, values, e) => {
if (e.target.validity.valueMissing) {
return 'Value is required';
} else if (e.target.validity.tooShort) {
return 'Value is too short';
} else if (e.target.patternMismatch) {
return 'Value does not match the required';
}
},
})
/>
Generated props are now memoizable (no more unnecessary re-renders)
In the past a change to an input resulted in re-rendering the entire form. That is not longer the case. The props generated by the input calls are now memoizable. This means that memoized input components will not re-render if their values remain the same.
const MemoizedInput = React.memo((props) => (
<input {...props} />
));
const MyForm = () => {
const [formState, { text, password }] = useFormState();
return (
<>
{/* these inputs only re-render if their values actually changed */}
<MemoizedInput {...text('username')} />
<MemoizedInput {...password('password')} />
</>
)
}
π¦ Other Changes
A special thanks to all the contributors that helped make this release possible! πββοΈ