Why build your forms with Redux Form

When I usually create forms for my React/Redux applications I tend to keep the value of the inputs on the application state, with little to no editing, (because my forms are usually simple), I never stopped to realize what that means. But when I and my team at ThoughtWorks faced a project with more complex form requirements, we started to wonder if it was worth to do all that Redux boilerplate to keep our inputs values into our application state.

In our discussion, I heard things like: "It is just a form!", "Do we really need the input values in our application state?".

After a lot of talk, we started to consider using the library Redux Form by Erik Rasmussen, but it arose other questions like "It will remove our flexibility to make custom behaviors, won’t it?".

The end of this story is that we actually decided to use Redux Form and I thought that sharing why may save you some time.

Why have the form values on application state?

Let’s get some context

The history of web development shows a move to increase the responsibility of the client side application, which in the past was just the HTML and all the work was made on server — now we have very complex JavaScript applications.

These JavaScript applications have taken the responsibility from the DOM as we could see with famous libraries like jQuery, Angular and more recently React. Since this last one took attention from the community, it brought with it the concept of unidirectional data flow, which basically is that the data comes down from the component state (or from the application state if you are using a state container like Redux) to your UI and the UI is rendered based on that state. Events on the UI changes the state and the new state updates the UI. With that React was the first library to really take the input values from the DOM by using controlled components.

But what are controlled components?

Controlled components are just HTML inputs that always receive its value as a property. It also receives an event handler that will update the state when the user interacts with it.

It means that when the user types the letter “J” on the input, what is visible is not the same “J”, it may be an identical “J” that comes from the state, or whatever the event handler has put in there.

Ok but, that doesn’t answer the first question

By having all the application state in the JavaScript app and using controlled components we get a single source of truth and take full control over the application behavior.

In the context of a form, our React component is able to:

  • do instant validation;
  • control the input value format;
  • enable, disable, show or hide components given the state;
  • handle dynamic inputs.

Although it is highly recommended to use controlled components, it is also good to point the drawback that you will have to create event handlers for all your inputs and that may be a bunch of code that doesn’t make sense to the application.

What about Redux Form?

Now that is known why to keep the form data in the state and you reason if that makes sense for your application we can come back to our main subject. Given that the application uses React and Redux there are two main options: implements for each field an event handler that dispatches an action creators, and the reducer that will receive the action… All the redux stuff. Or we could use a library that does all this work for us.

Redux Form is a great option to do that job to you. It keeps track of all common application form state such as:

  • The fields that are in the form;
  • The values of each field;
  • The focused field;
  • If the field values are valid;
  • The fields that the user have interacted with;
  • If the form is being submitted;
  • If is happening any asynchronous validation.

Let’s take a look at a bit of code and see how to do a setup.

Here we connect the form component to Redux by decorating it with the high-order component reduxForm. It will also hand us the handleSubmit function, which will take care of the submission behavior.

The Field component takes our input component as its props and acts as a container, bringing the application state to the input component and binding the event handlers to update the state in store.

Look at the InputText component to see the props we receive from the Field.

One important point is that it's still a developer's responsibility to write the form and inputs components, this way the library does not take the flexibility from you to manage the behaviors of your form the way you want, or even add custom ones.

And to finish our integration we add a reducer that will handle the state changes of your form.

Simple isn't it.

Just one more point. Look that the default value of the input is defined when the high-order component reduxForm is called and comes to the input within the prop input and not from the react's prop defaultValue, this way we guarantee that our form values are all represented in the application state.

In summary, having all your form data in application state gives you control over its behavior and you can easily implement that on a React/Redux application with Redux Form.

I have created a repository on GitHub with the implementation above. I also recommend to check the Redux Form documentation (which is quite good) and also to watch Erik Rasmussen talk with more information about the library and the reasons to use that. To better understand the controlled component I suggest this post.

Thank's Daniela Araújo and Roberto Soares for the review.

Hope it helps.

Show your support

Clapping shows how much you appreciated Guilherme Gonçalves’s story.