Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Hook Forms - Adding Dynamic Rows of Fields

I'm using React Hook Form library. https://react-hook-form.com

If it's a simple form like Student Name, and Student Age, the application is quite simple.

const { register, handleSubmit, formState: { errors } } = useForm();

I just create those two input fields and register them.

               <div className="w-full flex flex-col mt-4">
                  <label>Name</label>
                  <input
                    type="text"
                    placeholder="Enter Name" {...register("name")}
                  />

                </div>
                <div className="w-full flex flex-col mt-4">
                  <label>Age</label>
                  <input
                    type="text"
                    placeholder="Enter Age" {...register("age")}
                  />

                </div>
                <div>
                  <button onClick={handleSubmit(submitData)}>
                    Update
                  </button>
                </div>

The submitData function will get the formData which can be used. The handleSubmit binds the registered fields to formData

const submitData = async formData => {
  console.log(formData)
}

The formData will look as below:

{"name":"test", "age":"27"}

My requirement is to make this form dynamic, by allowing me to add many students. I should be able to repeat a set of these fields with a button called "Add Student". Every time I add a new student, it should create a new row of these two fields where I can add new students names. finally, the output of the formData should look like an array of students:

[{"name":"test1", "age":27},{"name":"test2", "age":28},{"name":"test3", "age":29} ]

I can create the UI to add the new fields, but I don't know how to bind them to the formData in react hook form. In the documentation, I couldn't find how to do this with react hook form.

Please help.

like image 403
asanas Avatar asked Sep 02 '25 01:09

asanas


1 Answers

I tried the following:

I created a state as follows:

const [items, setItems] = useState([0,1,2])

I can update this when I add/remove items.

Now, for the fields, I wrapped them into a map as follows:

{items.map(i => (
    <div>
        <div className="w-full flex flex-col mt-4">
            <label>Name</label>
            <input
            type="text"
            placeholder="Enter Name" {...register(`items[${i}].name`)}
            />

        </div>
        <div className="w-full flex flex-col mt-4">
            <label>Age</label>
            <input
            type="text"
            placeholder="Enter Age" {...register(`items[${i}].age`)}
            />

        </div>
    </div>
))}

This works.

like image 119
asanas Avatar answered Sep 05 '25 06:09

asanas