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?".
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
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
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
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.
Update #1 (2018–10–21)
One of the things people question me when discussing about this post is:
“Do We really need to use Redux store to keep the form data?”. My answer is no. By the time I wrote this post Redux was hype and Redux-Form didn't had an established alternative, but nowadays we have great options such as Formik and Final-Form, and both use React's component state.
My approach when writing a Redux application is keep all the data that matters to the application in the in the application state as long as it makes sense. But the point is, reason about what make more sense for your application and pick your choice.
Hope it helps.