Skip to content
Advertisement

how to get data from dynamically created input fields react

I’m trying to capture the inputs of dynamically created input fields and I’m only able to get the first set of exercise fields(Exercise, Reps, Sets)

import { useState } from "react";
export default StackTest;

function StackTest() {
  const [formData, setFormData] = useState({
    title: "",
    date: "",
    exercises: [{ Exercise: "benchpress", Reps: "5", Sets: "5" }],
  });

  const handle = (e, type, index) => {
    setFormData({
      title: formData.title,
      date: formData.date,
      exercises: [
        {
          Exercise: type === "E" ? e : formData.exercises[index].Exercise,
          Reps: type === "R" ? e : formData.exercises[index].Reps,
          Sets: type === "S" ? e : formData.exercises[index].Sets,
        },
      ],
    });
  };

  const updateForm = (e) => {
    setFormData((currentFormData) => ({
      ...currentFormData,
      [e.target.name]: e.target.value,
    }));
  };

  const handleAddExercise = (e) => {
    e.preventDefault();
    setFormData((currentFormData) => {
      return {
        ...currentFormData,
        exercises: [
          ...currentFormData.exercises,
          { Exercise: "benchpress", Reps: "5", Sets: "5" },
        ],
      };
    });
  };

  return (
    <>
      <form action="">
        <label htmlFor="">title</label>
        <input
          type="text"
          name="title"
          value={formData.title}
          onChange={updateForm}
        />
        <label htmlFor="">date</label>
        <input
          type="text"
          name="date"
          value={formData.date}
          onChange={updateForm}
        />

        {formData.exercises.map((exercise, index) => {
          return (
            <div key={index}>
              <input
                placeholder="exercise"
                onChange={(e) => handle(e.target.value, "E", index)}
              />

              <input
                placeholder="reps"
                onChange={(e) => handle(e.target.value, "R", index)}
              />
              <input
                placeholder="sets"
                onChange={(e) => handle(e.target.value, "S", index)}
              />
              <button onClick={handleAddExercise}>Add Exercise</button>
            </div>
          );
        })}
      </form>
    </>
  );
}

Whenever I type in one of the added exercise fields it will just remove it after the first character. I also tried to add an if statement in the handle function to check if the index was the same but as I’m new to react and coding in general I may have implemented that wrong.

Advertisement

Answer

The issue is that you’re overwriting the contents of your exercises array when you need to create a copy of it and mutate it.

The simplest solution would be to create a copy of your Exercises array, make any mutations needed and then update your state.

import { useState } from "react";
export default StackTest;

function StackTest() {
  const [formData, setFormData] = useState({
    title: "",
    date: "",
    exercises: [{ Exercise: "benchpress", Reps: "5", Sets: "5" }],
  });

  const handle = (e, type, index) => {

    let localExer = [ ...formData.exercises ];
    localExer[index].Exercise = (type === "E" ? e : formData.exercises[index].Exercise)
    localExer[index].Reps = (type === "R" ? e : formData.exercises[index].Reps)
    localExer[index].Sets = (type === "S" ? e : formData.exercises[index].Sets)

    setFormData({
      title: formData.title,
      date: formData.date,
      exercises: [ ...localExer],
    });

  };

  const updateForm = (e) => {
    setFormData((currentFormData) => ({
      ...currentFormData,
      [e.target.name]: e.target.value,
    }));
  };

  const handleAddExercise = (e) => {
    e.preventDefault();
    setFormData((currentFormData) => {
      return {
        ...currentFormData,
        exercises: [
          ...currentFormData.exercises,
          { Exercise: "benchpress", Reps: "5", Sets: "5" },
        ],
      };
    });
  };

  return (
    <>
      <form action="">
        <label htmlFor="">title</label>
        <input
          type="text"
          name="title"
          value={formData.title}
          onChange={updateForm}
        />
        <label htmlFor="">date</label>
        <input
          type="text"
          name="date"
          value={formData.date}
          onChange={updateForm}
        />

        {formData.exercises.map((exercise, index) => {
          return (
            <div key={index}>
              <input
                placeholder="exercise"
                onChange={(e) => handle(e.target.value, "E", index)}
              />

              <input
                placeholder="reps"
                onChange={(e) => handle(e.target.value, "R", index)}
              />
              <input
                placeholder="sets"
                onChange={(e) => handle(e.target.value, "S", index)}
              />
              <button onClick={handleAddExercise}>Add Exercise</button>
            </div>
          );
        })}
      </form>
    </>
  );
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement