Bill
Bill

Reputation: 5150

React: How to remove an item from an array in useContext via reducer

I've defined the initial state as below, and I've filled the objectArray with a few objects

const InitialState: StateInterface = {
  draw: 0,
  objects: {
    objectArray: [],
    selectedArray: [],
  },
  tools: {
    selector: false,
    snap: false,
  },
};

And I can add an object with

    case 'ADD_OBJECT':
      return {
        ...state,
        objects: {
          ...state.objects,
          objectArray: [...state.objects.objectArray, action.value],
        },
      };

The objects in the array looks like

{name: 'selection', age:15, size'12'}, {name: 'selection', age:12, size'5'}

I want to dispatch the object that I want to be deleted

dispatch({ type: DELETE_OBJECT, value: {name: 'selection', age:15, size'12'} });

I made the reducer

    case 'DELETE_OBJECT':
      return {
        ...state,
        objects: {
          ...state.objects,
          objectArray: [...state.objects.objectArray.pop(action.value)],
        },
      };

But I cant figure out how to remove the object contained in action.value from objectArray

Upvotes: 0

Views: 528

Answers (3)

Jayce444
Jayce444

Reputation: 9063

Well a simple approach would just be to filter the array based on the given value object, e.g.

case 'DELETE_OBJECT':
    return {
    ...state,
        objects: {
          ...state.objects,
          objectArray: state.objects.objectArray.filter(obj => (
              obj.name !== action.value.name &&
              obj.age !== action.value.age &&
              obj.size !== action.value.size
          ))
    },
};

Or, if you're sure the properties will be in the same order:

case 'DELETE_OBJECT':
    return {
    ...state,
        objects: {
          ...state.objects,
          objectArray: state.objects.objectArray.filter(obj => (
              JSON.stringify(obj) !== JSON.stringify(action.value)
          ))
    },
};

If you have lodash, it has a function called isEqual that would also do this in an easy, robust way.

Your approach could be dangerous though, since none of your objects' properties seem to be unique identifiers, so filtering could lead to the removal of more than one object from the array. Just something to be aware of

Upvotes: 0

Asaf Aviv
Asaf Aviv

Reputation: 11770

If they are the same reference(which would probably be true) you can simply do

objectArray: state.object.objectArray.filter(obj => obj !== action.value)

Or you can simply pass the index of the object in your action instead of the object itself

objectArray: state.object.objectArray.filter((_, i) => i !== action.index)

Upvotes: 1

Jai
Jai

Reputation: 74738

You have to filter it out to return the other objects instead of the passed one:

objectArray: state.objects.objectArray.filter(obj => (obj.name !== action.value.name && obj.size !== action.value.size && obj.age !== action.value.age))]

Array.prototype.filter() method returns a new Array.

Upvotes: 0

Related Questions