1

I have an App with 2 inputs where you can choose 1 muscle and a number of exercices for this muscle.

I added an "Add" button to duplicates these inputs to add a new muscle to work with its number of exercices.

The problem is, when I change an input, all same inputs will change because they have the same key (I guess).

Anyone can show me how to solve this ?

Here is my code :

import { Formik, Form, Field } from "formik";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { getAllMuscles, numberOfExercices } from "../helpers/dataModuler";
import { setInLocalStorage } from "../helpers/localStorageHandler";

export const ProgramForm: React.FC<{}> = () => {
  const [numberOfMusclesInProgram, setNumberOfMusclesInProgram] = useState(1);

  const navigate = useNavigate();

  const listOfMuscles = getAllMuscles();

  const initialValues = {
    numberOfExercices: 0,
    muscle: listOfMuscles[0]
  };

  const handleSubmit = (values: {}) => {
    setInLocalStorage("program", values);

    navigate("/programme");
  };

  return (
    <>
      <Formik
        initialValues={initialValues}
        onSubmit={(values) => handleSubmit(values)}
      >
        <Form>
          <div id="container">
            {[...Array(numberOfMusclesInProgram)].map((n, i) => (
              <DisplayMuscleInProgram key={n} />
            ))}
          </div>

          <button
            onClick={() =>
              setNumberOfMusclesInProgram(numberOfMusclesInProgram + 1)
            }
            type="button"
            className="rounded-md border"
          >
            Add
          </button>

          <div className="text-center">
            <button
              type="submit"
              className="mt-8 rounded-lg bg-primary p-2 text-white"
            >
              Let's gooooo 
            </button>
          </div>
        </Form>
      </Formik>
    </>
  );
};

export const DisplayMuscleInProgram = (props: { key: any }) => {
  const listOfMuscles = getAllMuscles();

  return (
    <>
      <div className="my-4 grid grid-cols-5 justify-between gap-5">
        <Field
          as="select"
          className="col-span-3 rounded-lg bg-lightGray p-3"
          name={`muscle-${props.key}`}
        >
          {listOfMuscles.map((muscle, key) => (
            <option key={key}>{muscle}</option>
          ))}
        </Field>
        <Field
          as="select"
          className="col-span-2 rounded-lg bg-lightGray p-3"
          name="numberOfExercices"
        >
          {numberOfExercices(10)}
        </Field>
      </div>
    </>
  );
};
Johan
  • 2,088
  • 2
  • 9
  • 37

1 Answers1

0

In ProgramForm replace <div id="container" /> with the following (replacing key={n} with key={i}):

<div id="container">
  {[...Array(numberOfMusclesInProgram)].map((n, i) => (
    <DisplayMuscleInProgram key={i} />
  ))}
</div>

Alternatively, you may try:

<div id="container">
  {[...Array(numberOfMusclesInProgram).keys()].map((n) => (
    <DisplayMuscleInProgram key={n} />
  ))}
</div>

Source: https://stackoverflow.com/a/33352604/975164

Currently, all your inputs have exactly the same name because of the following lines in DisplayMuscleInProgram:

<Field
  as="select"
  className="col-span-3 rounded-lg bg-lightGray p-3"
  name={`muscle-${props.key}`} // this line
>

React docs recommend using someEntity.id as keys and warn against using indexes as keys when the order of list items is expected to change. However, in this case, I believe you will be safe.

As a side note: Since you are using Formik, I recommend using Formik's built-in <FieldArray /> for this purpose i.e. add more inputs to the form on button click. You may read more about it here: https://formik.org/docs/api/fieldarray

Irfanullah Jan
  • 3,336
  • 4
  • 24
  • 34
  • Hello thank you very much for your help. I tried both of your code and nothing work :/. I logged `i` and `n` and one is undefined, other is null. Why do I have no data in `i` and `n` ? – Johan Aug 12 '22 at 14:45
  • 1
    Ah thanks, it works ! The problem was just "key=", I had to give it a unique name. Thank you ! – Johan Aug 12 '22 at 14:48