Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Set unique key for useState with multiple inputs

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).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>
    </>
  );
};

>Solution :

In ProgramForm replace <div id="container" /> with the following (replacing n with 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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading