Building a Dynamic, Controlled Form with React
React makes building UI’s in JavaScript easy, but some things can still be a bit tricky to wrap your head around, things like dynamic forms. A dynamic form is one where the user is able to decide how many inputs there should be. For this code along, we’re going to have standard inputs for a cat owner’s name and a short description, and then dynamically add cat inputs. Each new cat will have a name and age, just for fun.
Deciding on what we want
Planning is crucial with React, it can save you so much time if you wireframe out what you want before you start coding. We know what it will look like, but how will it be made? I like to have a little React checklist:
1. What components will I need?
2. Which of them will have state?
3. Are there events that we need to deal with?
In this case, I feel like it would read nicely to have a main Form component, and then CatInputs components that we can just render as we go. As for state, our Form component will need it, since we’ll control each input. But our CatInputs components will not require state, since we can just pass everything in as props.
Finally, there are 3 events: we need to handle the form getting submitted, we need to handle changes to each input, and we need to handle the button that adds new inputs.
Order of Attack
In general, I like to render whatever I need first, and then start working on the interactivity. In this case, we’ll render the static base Form, then figure out how to render the new inputs, and then finally we’ll deal with controlling them. For the sake of this tutorial, I will build everything in the Form component, and then once everything works, I’ll refactor the proper sections into a CatInputs component.
Getting started: render()
Let’s build out the non interactive part of the form first:
If you’re following along, this is basically what we made (yours will look different, I added some styling):
Using arrays for dynamic inputs
Before we code, we should talk about how we are going to do this. Basically, we’re going to have an array of cat objects in our state. Each object will have a name and age value. Our Form will iterate over this list and create two new inputs for the name and age. When we click the “add new cat” button, we’ll add a new object to our array. Since this will change our state, it will trigger a re-render. Then, our form will iterate over this new list of cats, it will add another pair of inputs.
To start, let’s just worry about putting the first blank cat object into our state, and then render that:
Adding inputs
Since our form is creating two new inputs, we know that the iteration aspect is working. But for it to truly be dynamic, we have to be able to let the user add the inputs. React’s state feature makes this really easy. We just need to give our component a method that adds a new blank cat to our array. Since we’re clicking a button inside a form now, we’ll also need to add a handleSubmit method which will stop our form.
Controlling the forms
Now that we have our dynamic inputs down, let’s actually control them. Here is the method that will control changes in all our inputs, static and dynamic, and our final state