score:3

Accepted answer

there are 3 problems in your code:

  1. you are setting the value of key to an object while the items is expected to have an array to ids.
// current
[key]: {
 ...prevstate[key],
 [x.id]: undefined
}

// expected
[key]: prevstate[key].filter(item => item.id === matchingid)
  1. if you intend to remove an object from an array based on some condition, you should be using filter as pointed out in owen's answer because what you are doing is something else:
const a = { xyz: 123, xyz: undefined };
console.log(a); // { xyz: undefined} - it did not remove the key
  1. to make your code more readable, it is expected to manipulate the entire object items and then, set it to the state once using setitems - in contrast to calling setitems multiple times inside a loop and based on some condition.

    this makes your code more predictable and leads to fewer re-renders.

also, the solution to your problem:

// define this somewhere
const initial_state = {
  "some_id1": [
    {
      "id": 93979
    },
    {
      "id": 93978
    }
  ],
  "some_id2": [
    {
      "id": 93961
    },
    {
      "id": 93960
    }
  ]
};

// state initialization
const [items, setitems] = react.usestate(initial_state);

// handler to remove the nested object with matching `id`
const removebynestedid = (id, items) => {
  const keys = object.keys(items);
  const updateditems = keys.reduce((result, key) => {
    const values = items[key];
    // since, we want to remove the object with matching id, we filter out the ones for which the id did not match. this way, the new values will not include the object with id as `id` argument passed.
    result[key] = values.filter(nesteditem => nesteditem.id !== id)
    return result;
  }, {});
  setitems(updateditems);
}

// usage
removebynestedid(93961, items);

score:0

your way solution

for (const key in items) {
    if (object.hasownproperty.call(items, key)) {
        const element = items[key];
        element.foreach(x => {
            if (x.id === singleitem.id) {
                setitems(prevstate => ({
                    ...prevstate,
                    //filter will remove the x item
                    [key]: element.filter(i => i.id !== x.id),
                }))
            }
        })
    }
}

short solution.

for(const k in items) items[k] = items[k].filter(x => x.id !== singleitemid);

const items = {
  "some_id1": [
    {
      "id": 93979,   
    },
    {
      "id": 93978,
    }
  ],
  "some_id2": [
    {
      "id": 93961,
    },
    {
      "id": 93960,
    }
  ]
}

const singleitemid = 93979;
for (const k in items) items[k] = items[k].filter(x => x.id !== singleitemid);

console.log(items);
//setitems(items)

score:0

you could try using the functional update.

const [data, setdata] = [{id:1},{id:2},{id:3}...]

once you know the id which you need to remove.

setdata(d=>d.filter(item=>item.id !== id));

score:1

probably a simple reduce function would work, loop over the entries and return back an object

const data = {"some_id1": [{"id": 93979},{"id": 93978}],"some_id2": [{"id": 93961},{"id": 93960}]}
const remove = ({id, data}) => {
  return object.entries(data).reduce((prev, [nextkey, nextvalue]) => {
    return {...prev, [nextkey]: nextvalue.filter(({id: itemid}) => id !==  itemid)}
  
  }, {})

}

console.log(remove({id: 93961, data}))


Related Query

More Query from same tag