DEV Community

Cover image for A simple React Form solution

A simple React Form solution

Duc Ng
JS enthusiast / 17y tinkering with screens & code.
Updated on ・2 min read

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:

    <span>Email</span><input id=“email” />
    <button type=“submit”>Submit</button>

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>
    <div class=“field-error” />

    <button type=“submit” className=“btn btn-primary”>Submit</button>

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} >
        { (opt => <option value={opt.value}>{opt.label}</option>}
    {this.state.errors[‘dropdown’] && <div class=“field-error” />}

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

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?

Discussion (4)

asparallel profile image
AsParallel • Edited

Seems clean enough. I'd also recommend taking a look at reactive forms as well. It implements this type of thing with less boilerplate, while also making it easy to support things like dependent field validation, schema and form composition definition as a unit, field and form level status and value update changes, etc.

It's not for react, but the paradigm is painless, functional and clean.

ngduc profile image
Duc Ng Author • Edited

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

ngduc profile image
Duc Ng Author

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

ngduc profile image
Duc Ng Author

This project was renamed & moved to -