State of React uncontrolled forms in 2022
Forms are the backbone of the web – still in 2022! So for a good start into the year, I decided to refresh my knowledge on the current state of web forms with React. It's actually quite nice what you can achieve easily with uncontrolled React form components and Constraint Validation API. Use the platform and let the browser do most of the heavy lifting!
This demo is based on static HTML export with nextjs. Please refer on their documentation for further details.
To provide basic accessibility, semantic HTML elements were used. Invalid states result in
aria-messages which are connected to the
input-elements through the correct attributes. In the accessibility section of the web.dev tutorial, they use
aria-describedby. I actually think that
aria-invalid combined with
aria-errormessage is a stronger solution and prefer that. If anyone has better experiences in this regard, I would be very happy to receive feedback.
Another great accessibility enhancement were focussing the first invalid input element when trying to submit an incomplete form. Also rendering visually hidden information (e.g.
<fieldset> with a
<legend>) is important to provide users with visual impairments with them same information.
Isomorphic React with pre-rendered HTML gives a lot of power in our hands. But with that, I think, comes the responsibility to provide a good experience for users who don’t have client-side rendering (CSR). Still in 2022!
action prop with the preferred
method and still provide basic validation and a workable form.
Which rules result in HTML attributes are configured here (as a start). All other validation constraint will be handled with custom validator functions. They should therefore be available here. In this configuration, validation attributes have a higher priority compared to custom validator functions. For example if we decide to delete
required from the
htmlValidationAttributes, we should add a validator function with the signature of
() => (value) => boolean and handle it in
The properties of the ValidityState Interface are a bit wild in my opinion and not always attributable to the corresponding HTML validation attribute. But it basically says "yes, I am valid" or if not, it gives you a reason. I also started adding a mapping from the validation attributes to the property of the
Nowadays, it makes definitly sense to use
accent-color. This gives you at least a little power to syle “hard-to-style” elements like
input[type=checkbox] and align them with your brand style.
Also the combination of
outline-offset is really nice, since this is a very common visual requirement for focus states, and often needed some quirks to achieve that.
In the end, this is a very simple solution. But if you like this approach, using the browser’s capabilities with uncontrolled React form elements, React Hook Form might be worth to be checked out. Thanks for reading!