0

I'm building a dynamic form using React JS. in one of my form i've created an input form of 10. to get clean code i've created an object and map through it for the form. code is below.

{homeAmeneties.map((home) => {
    <div className="h-8 flex justify-end  rounded-md pr-10">
                    <input
                      type="number"
                      onInput={(event) =>
                        (event.target.value = event.target.value.slice(
                          0,
                          event.target.maxLength
                        ))
                      }
                      maxLength="3"
                      onChange={(e) => updateVal(e, home.name)}
                      className="border-[1px] w-1/2  border-black rounded-md h-full focus:outline-none px-2"
                    />
                  </div>
})}

then afterwards i've created a useState([]) and used a conditional to check if the field exists, so that i can only update the value.

const [amen, setAmen] = useState([]);
const updateVal = (e, type) => {
amen.some((item) => {
        if (item.name === type) {
          setAmen({ name: type, val: e.target.value });
        } else {
          setAmen({ name: type, val: e.target.value });
        }
      });
}

when i run this it throws an error. amen.some is not a function error. what i want to achieve is, initially the state is empty. but when one field value changes it add it to the array as { name: type, val: e.target.value }. so before it's added we check if the type already exists. if so then we change the value of that exact array of object. but if the type doesn't exist it create an new object. How can i do that?

2 Answers 2

1

I have 3 things to point out:

  • You said you created an object and map through it to render the input fields. Actually, you can only map over arrays in JavaScript.
  • In your updateVal method call, you are setting the react state to an object instead of an array.
  • I wouldn't recommend using Array.some () to update the state. Instead, I would use Array.findIndex ().

Solution

const updateVal = (e, type) => {
  const updatedAmen = [ ...amen ]; // create a new array to avoid mutating the state directly

  // check if an input already exists with the said type & get the index position
  const exisitingAmenIdx = updatedAmen.findIndex((a) => a.name === type);

  if (exisitingAmenIdx >= 0) {
    updatedAmen[exisitingAmenIdx].val = e.target.value;
  } else {
    updatedAmen.push({
      name: type,
      val: e.target.value
    })

    // finally update the state
    setAmen(updatedAmen)
  }
};
Sign up to request clarification or add additional context in comments.

2 Comments

it throws an error TypeError: Cannot set properties of undefined (setting 'val')
@MohammedBekele, there was a typo in the solution. Please try again, I've updated the answer.
0

It's because you're setting the state value of amen to be the object you're aiming to append to the array:

  setAmen({ name: type, val: e.target.value });

  // amen = { name: type, val: e.target.value }

Since it changes from being an Array, Array.some() is not going to be defined. One way you can go about this is:

  setAmen([{ name: type, val: e.target.value }, ...amen]);

Create a new Array so react will update the state. Add the new element, and then use the spread operator ...amen to extract the other elements.

1 Comment

Your solution does the update of the array, but it is still giving the same error

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.