Home > Net >  Adding data to an existing array of objects through an onChange handler
Adding data to an existing array of objects through an onChange handler

Time:09-30

I have an array of objects

[
  {
    "0": {
      "title": "Jessica Simpson",
      "id": "324352342323432",
      "url": "image-url.jpg",
      "colourScheme": "",
      "type": "",
      "enabledUnits": ""
    },
    "1": {
      "title": "Bill Murray",
      "id": "5qocDvdm9XETFz33p725IG",
      "url": "image-url.jpg",
      "colourScheme": "",
      "type": "",
      "enabledUnits": ""
    },
  }
]

I'm attempting to add update the colourScheme value inside the object via an onChange event handler.

OnChangeHandler

  const createOnChangeHandler = (floorPlan: FloorPlan, property: 'colourScheme' | 'type') => (
    e: React.ChangeEvent<HTMLInputElement>
  ) => {

      console.log(( e.target.value ))
      const itemList = floorPlans.concat();
      const index = itemList.findIndex((i) => i.id === floorPlan.id);
      itemList.splice(index, 1, {...floorPlans, [property]: e.target.value});
  };

But it's being added outside the object. For example... notice "colourScheme": "Black" is outside.

  {
    "0": {
      "title": "Angeline Espaze",
      "id": "5qocDvdm9XETFz33p725IG",
      "url": "image-url.jpg",
      "colourScheme": "",
      "type": "",
      "enabledUnits": ""
    },
    "colourScheme": "Black"

  }
]

Where i would like

[
  {
    "0": {
      "title": "Angeline Espaze",
      "id": "5qocDvdm9XETFz33p725IG",
      "url": "image-url.jpg",
      "colourScheme": "Black",
      "type": "",
      "enabledUnits": ""
    },
  }
]

I think the issue is with itemList.splice? inside the onChange

CodePudding user response:

The problem is:

  1. You're spreading the wrong thing into the new object, and

  2. You're not calling a state setter.

I wouldn't use splice for this at all, you can do the object update while copying the array rather than afterward. Instead (see comments):

const createOnChangeHandler = (floorPlan: FloorPlan, property: 'colourScheme' | 'type') => (
    e: React.ChangeEvent<HTMLInputElement>
) => {
    const {value} = e.target;
    // Call the state setter; because we're updating state based on existing state, it's
    // best to use the callback version
    setFloorPlans(floorPlans => {
        // Return a new array with a replaced object
        return floorPlans.map(entry => {
            if (entry.id === floorPlan.id) {
                // Create a replacement object
                return {...entry, [property]: value};
            }
            return entry; // No change to this object
        });
    });
};

That's assuming you're using hooks. If you're using a class component, use this.setState instead:

const createOnChangeHandler = (floorPlan: FloorPlan, property: 'colourScheme' | 'type') => (
    e: React.ChangeEvent<HTMLInputElement>
) => {
    const {value} = e.target;
    // Call the state setter; because we're updating state based on existing state, it's
    // best to use the callback version
    this.setState(({floorPlans}) => {
        // Return a new array with a replaced object
        return {floorPlans: floorPlans.map(entry => {
            if (entry.id === floorPlan.id) {
                // Create a replacement object
                return {...entry, [property]: value};
            }
            return entry; // No change to this object
        }});
    });
};

CodePudding user response:

Try below code.

 const createOnChangeHandler = (floorPlan: FloorPlan, property: 'colourScheme' | 
  'type') => ( e: React.ChangeEvent<HTMLInputElement>) => {
   
   let lclfloorPlans = [...floorPlans];

   lclfloorPlans.forEach(item => {
   for (var key in item) {
    if (item[key].id === floorPlan.id) {
      item[key][property] = e.target.value;
      break;
    }
  }
});

setFloorPlans(lclfloorPlans); // assign to your state value
};
  • Related