Following a React tutorial, I see this code in a reducer to remove a message from an array using its ID:
Wouldn't this be better written as:
else if (action.type === 'DELETE_MESSAGE') {
return {
messages: [
...state.messages.filter(m => m.id === action.id)
],
};
};
I thought for a second that filter
might modify state and return the same array but according to MDN it creates a new array.
Am I safe, and is my implementation correct?
Following a React tutorial, I see this code in a reducer to remove a message from an array using its ID:
Wouldn't this be better written as:
else if (action.type === 'DELETE_MESSAGE') {
return {
messages: [
...state.messages.filter(m => m.id === action.id)
],
};
};
I thought for a second that filter
might modify state and return the same array but according to MDN it creates a new array.
Am I safe, and is my implementation correct?
Share Improve this question edited Dec 22, 2016 at 6:50 softcode asked Dec 22, 2016 at 6:16 softcodesoftcode 4,64812 gold badges44 silver badges69 bronze badges 3- It appears the spread operator concats both arrays. see repl.it/EvXg/1 @Rajesh – softcode Commented Dec 22, 2016 at 6:38
- I wonder if there are performance reasons. Could the slice method be faster with a large array? – Scimonster Commented Dec 22, 2016 at 7:59
- @Scimonster That's what I was thinking. I don't understand their approach, it seems deceivingly inefficient. – softcode Commented Dec 22, 2016 at 16:49
1 Answer
Reset to default 17Yes. It would actually be a very clean solution. The trick is that, in Array#filter
, every element of an array is applied with a function that accepts more than one argument. Such a function, when returns a boolean value, is called predicate. In case of Array#filter
(and in fact, some other methods of Array.prototype
), the second argument is index of the element in source array.
So, given that you know the index, it's simply
(state, action) => ({
...state,
messages: state.messages.filter((item, index) => index !== action.index)
})
However, you don't know the index. Instead, you have a value of id
property. In this case, you're right, you simply need to filter the source array against this id
to only put elements that have value of id
that is not equal to target id
:
(state, action) => ({
...state,
messages: state.messages.filter(item => item.id !== action.id)
})
Take a note: no need to spread state.messages
and put them back into a new array. Array#filter
doesn't mutate the source array, which is nice.
So, it's !==
instead of ===
. You were close.