DEV Community

Cover image for A simple React Form solution
Duc Ng
Duc Ng

Posted on • Edited on

A simple React Form solution

React is great. I get it, it lets us create Components like a snap. But sometimes, especially for some old-timers like me who used to work with pure Javascript and HTML tags in the past, I feel that nowadays, there is more work to wire things together to have a simple thing working as expected like before.

For example, to create a simple form, we can just quickly code like this:

<form>
    <span>Email</span><input id=“email” />
    <button type=“submit”>Submit</button>
</form>
Enter fullscreen mode Exit fullscreen mode

Then came XHTML validation and new requirements (add a dropdown & form validation), I have learned to create a “proper” form with “valid” tags and attributes:

<form action=“/someendpoint” method=“POST”>
    <label for=“email”>Email</label>
    <input type=“text” id=“email” />
    <div class=“field-error” />

    <label for=“dropdown”>Dropdown</label>
    <select id=“dropdown”>
        <option value=“OPTION1”>Option 1</option>
        <option value=“OPTION2”>Option 2</option>
    </select>
    <div class=“field-error” />

    <button type=“submit” className=“btn btn-primary”>Submit</button>
</form>
Enter fullscreen mode Exit fullscreen mode

Fast forward to React world, I were told to wire the existing form to React handler functions and state. After some sweats and tears, now my code looks like this.

<form action=“/someendpoint” method=“POST”>
    <label htmlFor=“email”>Email</label>
    <input type=“text” id=“email” onChange={this.onEmailChange} />
    {this.state.errors[‘email’] && <div class=“field-error” />}

    <label htmlFor=“dropdown”>Dropdown</label>
    <select id=“dropdown” onChange={this.onSelectChange} >
        {this.state.options.map (opt => <option value={opt.value}>{opt.label}</option>}
    </select>
    {this.state.errors[‘dropdown’] && <div class=“field-error” />}

    <button type=“submit” className=“btn btn-primary” onChange={this.onSubmit}>Submit</button>
</form>
Enter fullscreen mode Exit fullscreen mode

Ok, not too bad, there is a little more code added but the benefits outweighed the cons right? “Umh, right…”, (My old timer voice sounded reluctant).

Days went by, more requirements came, my forms grew longer and longer, I had to duplicate the code to multiple places and make sure they’re all in sync when there are changes to stylings, JSX, etc. across the app.
One day, I felt tired and decided to look around for some libraries to save my soul. Npm shows a long list of good libraries: tcomb, formik, final form, json schema form, etc. They all have different approaches to build my simple form. So I spent more time learning each of them. (JS fatigue, anybody?)

Among them, I found that formik is a great library that very close to all the requirements that I got: controlled fields, validation, easy to understand, etc. But I always want to describe my form in a short and natural way as much as possible, so I opened my VSCode and put together a form spec like this (based on formik) which I want to achieve:

A simple form spec

Over one weekend, I spent some time tried to implement that spec and got some success. So far it has worked very well for my pet projects:

Demo Link

Let me know what you think, is it simple enough or there is a better way to achieve that?

Top comments (3)

Collapse
 
ngduc profile image
Duc Ng • Edited

Reactive-forms is Angular's. I'm working on dependent fields (dynamic form) now. It's coming soon :)
Update: it's done.

Collapse
 
ngduc profile image
Duc Ng

Sounds good. I will check it out to see if I can bring those features to the roadmap. Thanks AsParallel!

Collapse
 
ngduc profile image
Duc Ng

This project was renamed & moved to - github.com/ngduc/ui-form-field