0

Im rendering an array of objects, then I'm trying to add a new property to it via a function, but that new property value does not render. When I console log the object I can see that the property and the new value are there. That new property is tag. I assume this has something to do with e.preventDefault(). How can I fix this?

const addTag = (e,id) => {
  e.preventDefault()
  let text = e.target.tag.value
  let obj = stu.find(x => x.id === id)
  obj.tag = text
  console.log(obj)
}

  return (
    <div className="App">
      {stu.map((student, id) => (
          <div key={id}>
            <p>{student.email}</p>
            <p>{student.firstName}</p>
            <p>{student.tag}</p>
            <form onSubmit={(e) => addTag(e, student.id)}>
              <input type="text" id="tag"/>
              <button type="submit">Submit</button>            
            </form>
          </div>
      ))}
    </div>
  );
}
devAR
  • 349
  • 7
  • 21
  • 2
    *"I assume this has something to do with `e.preventDefault()`"* No, it's because React doesn't know that it needs to re-render the component. If `stu` is part of the component's state then you need to update it (by creating a new array/object). https://reactjs.org/docs/hooks-state.html . Related: [Correct modification of state arrays in React.js](https://stackoverflow.com/q/26253351/218196) – Felix Kling Apr 25 '22 at 19:19
  • Usually when objects (or variables in general) are to be changed during runtime react hooks are required. Preventdefault just prevents the default behaviour of the event. – m_k_s Apr 25 '22 at 19:22
  • Possibly a duplicate, though it refers to class components: [Updating an object with setState in React](https://stackoverflow.com/q/43638938/218196) – Felix Kling Apr 25 '22 at 19:27

1 Answers1

0

Your state variable is an array. Modifying objects in that array, (or even adding/removing elements entirely) will not cause react to re-render. The reference to the array must change. One easy way to do this is to copy the elements to a new array:

const addTag = (e,id) => {
  e.preventDefault()
  let text = e.target.tag.value
  let obj = stu.find(x => x.id === id)
  obj.tag = text
  setStu([...stu])
}

*you may run into issues since you're keying only on the element index. Consider changing your key value as well

isick
  • 1,467
  • 1
  • 12
  • 23