I understand the expectation for array.push()
to return the mutated array instead of its new length. And the desire to use this syntax for chaining reasons.
However, there is a built in way to do this: array.concat()
.
Note that concat
expects to be given an array, not an item. So, remember to wrap the item(s) you want to add in []
, if they are not already in an array.
newArray = oldArray.concat([newItem]);
Array chaining can be accomplished by using .concat()
, as it returns an array,
but not by .push()
, as it returns an integer (the new length of the array).
Here is a common pattern used in React
for changing the state
variable, based on its prior value:
// the property value we are changing
selectedBook.shelf = newShelf;
this.setState((prevState) => (
{books: prevState.books
.filter((book) => (book.id !== selectedBook.id))
.concat(selectedBook)
}
));
state
object has a books
property, that holds an array of book
.
book
is an object with id
, and shelf
properties (among others).
setState()
takes in an object that holds the new value to be assigned to state
selectedBook
is already in the books
array, but its property shelf
needs to be changed.
We can only give setState
a top level object, however.
We cannot tell it to go find the book, and look for a property on that book, and give it this new value.
So we take the books
array as it were.
filter
to remove the old copy of selectedBook
.
Then concat
to add selectedBook
back in, after updating it’s shelf
property.
Great use case for wanting to chain push
.
However, the correct way to do this is actually with concat
.
Summary:
array.push()
will return a number (mutated array’s new length).
array.concat([])
will return a new the “mutated array.
Technically, it returns a new array with the modified element added to the end, and leaves the initial arrays unchanged.
Returning a new array instance, as opposed to recycling the existing array instance is an important distinction, that makes it very useful for state objects in React applications, to get changed data to re-render.