Solid Final Form – Proof of Concept
Since its inception, Final Form was designed to outlive existing frameworks.
Five years ago, I challenged myself to create a form state management library that was framework independent. In 2017, the idea that maybe React wasn't the best place to manage application state was not nearly as common as it has become. Formik had just been released and took all of the form library NPM downloads for the following few years. Formik went all-in on React for state management. The current King of Forms in React is React Hook Form, again, betting all the marbles on React's state management prowess.
From the very beginning of Final Form, it was designed to outlive existing popular frontend frameworks. Form state is two things:
- more complicated than you think
- not inherently related to any frontend framework
When our great grandkids are filling out their applications for Space Academy, they are going to be entering data, be it with a keyboard or a neural implant, into a form field that is going to have some validation rules on it, and the UX is gonna SUCK because the engineers at Space Academy didn't spend enough effort making the form entry experience good.
Just because the form is rendered in the then-popular Neural4D-VR.js
UI
framework, the flow of the form data will be just like it is now.
Form State is framework independent.
Solid JS
I've been hearing rumors of this new React competitor getting more and more popular. I'd glanced at it a few times, but at a recent conference, I got to meet the creator, and generally sense the wind of interest headed in its direction.
The "no virtual DOM" and "reactivity" claims are incredibly intriguing.
[insert React is not reactive joke here]
What really put me over the edge to attempt what I'm about to present to you is realizing that Solid lets you tack on "directives" to your JSX, which are little functions that get to manipulate the DOM directly, a benefit of not having a virtual DOM. This could make a very interesting way to connect inputs to a form management library.
Especially if there were a form state management library that were framework agnostic... 🤔
Proof of Concept
What I'm about to show you is an example of what a Solid Final Form library
might look like. It calls useForm()
to create a form instance and expose its
API. Potentially all form state could be exposed via Solid's
signals. From the docs:
Signals are the most basic reactive primitive. They track a single value (which can be any JavaScript object) that changes over time.
In this proof of concept, I have only exposed values
and isSubmitting
, but
Final Form has a
veritable plethora of
other form state it manages.
useForm()
also gives us two
directives, field
and
error
. To connect an input (i.e. attach blur, change, and focus listeners) to
Final Form, we:
- Throw a
use:field
directly on the<input/>
- There is no step 2, you're done already!
- How fun are
<li>
gags?
The field
directive reads the name
prop on the input
and knows what field
it is.
To show errors, we don't have a name
prop, so we have to tell the error
directive with:
<span use:error="firstName" />
Here's the full form component:
export const App: Component = () => {// Create Formconst { error, field, handleSubmit, isSubmitting, values } = useForm(onSubmit,initialValues,validate);// Calculated Signalconst formattedValues = () => JSON.stringify(values(), undefined, 2);return (<form onSubmit={handleSubmit}><h1>Solid Final Form 🏁</h1><label><input name="firstName" placeholder="First Name" use:field /><span use:error="firstName" /></label><label><input name="lastName" placeholder="Last Name" use:field /><span use:error="lastName" /></label><label><select name="favoriteColor" use:field><option value="">Choose a color</option><option value="#FF0000">Red</option><option value="#00FF00">Green</option><option value="#0000FF">Blue</option></select><span use:error="favoriteColor" /></label><button type="submit" disabled={isSubmitting()}>Submit</button><pre>{formattedValues()}</pre></form>);};
In this 100-line proof of concept, what are the features we're getting?
- Realtime client side validation (as you fix errors, they go away)
- Tracking if a field is "touched" (focused and then blurred) to only show the error if a user has visited the field or attempted to submit the form
- Blocking submission when there are validation errors
- A signal to tell us if the form is being submitted
- None of that "Is the whole form rerendering? Waaahhh!! 😭🍼" nonsense that React gives us
- Render props? What are those??
- A robust battle-tested framework (300k weekly downloads) for managing our form state
Sandbox
Future
At the time of writing, this is just a fun Saturday morning fun project. I don't really feel like I have the bandwidth right now to pursue maintaining another open source library, but I'd be happy to work closely with anyone who would like to take this and run with it. You can find me on Twitter.