Redux: Remove item from array

What I’m doing wrong here?

const immutableReducer = (state = [0,1,2,3,4,5], action) => {
  switch(action.type) {
    case 'REMOVE_ITEM':
      // don't mutate state here or the tests will fail
      let newArr = [...state.slice(0,action.index)];
      return newArr;
    default:
      return state;
  }
};

const removeItem = (index) => {
  return {
    type: 'REMOVE_ITEM',
    index
  }
}

const store = Redux.createStore(immutableReducer);

https://learn.freecodecamp.org/front-end-libraries/redux/remove-an-item-from-an-array

Error in console:

// running test
Dispatching the removeItem action creator should remove items from the state and should NOT mutate state.
// tests completed

It would be correct to say that state isn’t being mutated. However, the way you are removing the item from the array needs a revision.

Right now, if you used the slice() method with action.index being your end index and 0 as your starting index, it would return back with that portion of the array

 let newArr = state.slice(0, 3) //[ 1, 2, 3 ]

We’re not creating a new array from a portion of the state array. We’re simply deleting that index in the state array.

So, we should use the .filter() array method, and only returning all the indices that don’t equal our index we want to remove

const immutableReducer = (state = [0,1,2,3,4,5], action) => {
  switch(action.type) {
    case 'REMOVE_ITEM':
      let newArr = [...state.filter((elem, idx) => { // [1,2,3,5]
        return idx !== action.index
      })];
      return newArr;
    default:
      return state;
  }
};

const removeItem = (index) => {
  return {
    type: 'REMOVE_ITEM',
    index
  }
}

const store = Redux.createStore(immutableReducer);
3 Likes

@DanStockham, I don’t understand why slice doesn’t work.

I’ve used it this way: state.slice(0, action.index).concat(state.slice(action.index + 1)), but it failed.

As it is said in the Remove Elements from an Array Using slice Instead of splice article of Functional Programming section,

the slice method does not mutate the original array, but returns a new one

Is this not a contraction of what you say?

We’re not creating a new array from a portion of the state array. We’re simply deleting that index in the state array.

Could you please help me understand, what am I missing?

I enter your new solution into the challenge, and I’ve gotten the same thing. However, I noticed a.slice(action.index + 1) Where does a come from? I think you were meaning to use state right?

When I replaced it with state it worked just like how you originally intended :slight_smile:

When I looked at my original answer, it does come across as contradicting. However, I was addressing in the context of your first solution:

let newArr = [...state.slice(0,action.index)];

This was only creating half of the array of what we needed, hence, why I mentioned we’re not creating a portion of the array. We want the whole array sans the element that falls under the passed index.

The reason I mentioned filter() is because it’s much terser and concise. That brings much value to your code because it will be more readable to other developers.

Instead of this:

let newArr = [...state.filter((elem, idx) => { // [1,2,3,5]
        return idx !== action.index
      })];
      return newArr;

you can also do: return state.filter((elem, index) => index !== action.index);

3 Likes

Yes you could do it that way to make it more terse. However, I was aiming for better reading for less experienced newbies

3 Likes