Search code examples
reactjsstateonchange

Find object in state and update property


I have a problem with a dynamic state I am setting. My first state looks like this:

const [exercises, setExercises] = useState([{
  id: 123,
  title: "Title here",
  category: "someCategory"
}])

A user then selects an item of this state. I create a second state representing the selected object, but adding additional properties to it. For instance I am adding and initializing the properties 'amount' and 'unit'.

const [selectedExercises, setSelectedExercises] = useState([{
  id: 123,
  title: "Title here",
  category: "someCategory",
  amount: 0,
  unit: ''
}])

I want the user to choose amount and unit from a form. How do I access and change those two properties in the state? Since I don't know the user's selection, I have to find the object within the state first.

I have tried things like (el being called from an input element somewhere):

setSelectedExercises([
  ...selectedExercises,
  (selectedExercises.find(exercise => exercise.title === el.title).amount = 1),
  ])

How do I find the object in question and update its amount property (for example in an onChange method)?


Solution

  • const [selectedExercises, setSelectedExercises] = useState([{
      id: 123,
      title: "Title here",
      category: "someCategory",
      amount: 0,
      unit: ''
    }]);
    
    // Your handler should look like this and 
    // you should call handleAmountChange(el.id, 1)
    
    function handleAmountChange(amount, id) {
      setSelectedExercises(prev => prev.map(selectedExercise => {
        if (selectedExercise.id === id) {
          return {
            ...selectedExercise,
            amount
          }
        }
    
        return selectedExercise;
      }));
    }
    

    A more generic function to change any property would look like this.

    function handleChange(id, property, value) {
      setSelectedExercises(prev => prev.map(selectedExercise => {
        if (selectedExercise.id === id) {
          return {
            ...selectedExercise,
            [property]: value
          }
        }
    
        return selectedExercise;
      }));
    }