score:231

Accepted answer

No. Never mutate your state.

Even though you're returning a new object, you're still polluting the old object, which you never want to do. This makes it problematic when doing comparisons between the old and the new state. For instance in shouldComponentUpdate which react-redux uses under the hood. It also makes time travel impossible (i.e. undo and redo).

Instead, use immutable methods. Always use Array#slice and never Array#splice.

I assume from your code that action.payload is the index of the item being removed. A better way would be as follows:

items: [
    ...state.items.slice(0, action.payload),
    ...state.items.slice(action.payload + 1)
],

score:0

The golden rule is that we do not return a mutated state, but rather a new state. Depending on the type of your action, you might need to update your state tree in various forms when it hits the reducer.

In this scenario we are trying to remove an item from a state property.

This brings us to the concept of Redux’s immutable update (or data modification) patterns. Immutability is key because we never want to directly change a value in the state tree, but rather always make a copy and return a new value based on the old value.

Here is an example of how to delete a nested object:

// ducks/outfits (Parent)

// types
export const NAME = `@outfitsData`;
export const REMOVE_FILTER = `${NAME}/REMOVE_FILTER`;

// initialization
const initialState = {
  isInitiallyLoaded: false,
  outfits: ['Outfit.1', 'Outfit.2'],
  filters: {
    brand: [],
    colour: [],
  },
  error: '',
};

// action creators
export function removeFilter({ field, index }) {
  return {
    type: REMOVE_FILTER,
    field,
    index,
  };
}

export default function reducer(state = initialState, action = {}) {
  sswitch (action.type) {  
  case REMOVE_FILTER:
  return {
    ...state,
    filters: {
    ...state.filters,
       [action.field]: [...state.filters[action.field]]
       .filter((x, index) => index !== action.index)
    },
  };
  default:
     return state;
  }
}

To understand this better, make sure to check out this article: https://medium.com/better-programming/deleting-an-item-in-a-nested-redux-state-3de0cb3943da

score:0

Deleting an item using redux in different ways.

Method 1: In that case is used createSlice( .. )

const { id } = action.payload; // destruct id
removeCart: (state, action) =>{
                 let { id } = action.payload;
                 let arr = state.carts.filter(item => item.id !== parseInt(id))
                 state.carts = arr;
               }

Method 2: In that case is used switch (... ), spread-operator

const { id } = action.payload; // destruct id

case actionTypes.DELETE_CART:  
     return {
        ...state,
        carts: state.carts.filter((item) => item.id !== payload)
      };

For both methods initialized this state:

  initialState: {
      carts: ProductData, // in productData mocked somedata     
    }

score:11

Another one variation of the immutable "DELETED" reducer for the array with objects:

const index = state.map(item => item.name).indexOf(action.name);
const stateTemp = [
  ...state.slice(0, index),
  ...state.slice(index + 1)
];
return stateTemp;

score:26

The ES6 Array.prototype.filter method returns a new array with the items that match the criteria. Therefore, in the context of the original question, this would be:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: state.items.filter(item => action.payload !== item),
  lastUpdated: Date.now() 
})

score:181

You can use the array filter method to remove a specific element from an array without mutating the original state.

return state.filter(element => element !== action.payload);

In the context of your code, it would look something like this:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: state.items.filter(item => item !== action.payload),
  lastUpdated: Date.now() 
})

Related Query

More Query from same tag