4 New Copying Array Methods That Come in Handy in React
Published: 2024-02-07 17:00:04


Arrays in JavaScript are either copying or mutating. This means that when you use a method on an array, it returns a new array or changes the original one.

Some codebases prefer to work with immutable data. For instance, in React applications, if you use `useState` with array

```jsx
const [fruits, setFruits] = useState(['banana', 'apple', 'orange']);
```

You should never change the state arrays (and objects) directly; instead, create a new array and then set it with the setter function.

```jsx
setFruits(fruits.sort()); // ❌

setFruits([...fruits].sort()); // ✅
```

That's when copying methods come in handy. They don't change the original array but instead return a new one - so you don't have to copy it manually with the spread operator `...`.

One important caveat is that these methods only create a shallow array copy. So, if you have, for example, an array of arrays, you should still be careful to not mutate the inner arrays.

ECMAScript 2023 release introduces four new copying array methods that allow data manipulation while preserving the original arrays. This update makes life easier for developers who adhere to functional programming principles in their codebases.

**`toSorted()`**, **`toReversed()`**, **`toSpliced()`**, and **`with()`** — Let's dive into how these methods compare with their traditional counterparts.

**1. `Array.prototype.toSorted()` vs. `Array.prototype.sort()`**

The traditional **`sort()`** method sorts an array in place, changing the original array.

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
animals.sort();
animals // ['cat', 'elephant', 'tiger', 'zebra']
```

In contrast, **`toSorted()`** creates a new sorted array

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
let sortedAnimals = animals.toSorted();
sortedAnimals // ['cat', 'elephant', 'tiger', 'zebra']
animals // ['tiger', 'zebra', 'elephant', 'cat']
``` 

**2. `Array.prototype.toReversed()` vs. `Array.prototype.reverse()`**

While **`reverse()`** modifies the original array

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
animals.reverse();
animals // ['cat', 'elephant', 'zebra', 'tiger']
```

**`toReversed()`** returns a new array that is the reverse of the original

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
let reversedAnimals = animals.toReversed();
reversedAnimals // ['cat', 'elephant', 'zebra', 'tiger']
animals // ['tiger', 'zebra', 'elephant', 'cat'];
``` 

**3. `Array.prototype.toSpliced()` vs. `Array.prototype.splice()`**

**`splice()`** changes the array by removing or replacing existing elements and/or adding new ones.

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
animals.splice(1, 2, 'monkey', 'giraffe');
animals // ['tiger', 'monkey', 'giraffe', 'cat']
```

**`toSpliced()`** is the copying version of **`splice()`**

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
let splicedAnimals = animals.toSpliced(1, 2, 'monkey', 'giraffe');
splicedAnimals // ['tiger', 'monkey', 'giraffe', 'cat']
animals // ['tiger', 'zebra', 'elephant', 'cat']
``` 

**4.** Direct assignment **vs.** **`Array.prototype.with()`**

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
animals[2] = 'lion';
animals // ['tiger', 'zebra', 'lion', 'cat']
```

Unlike a direct assignment, **with()** produces a new array with the specified change.

```jsx
let animals = ['tiger', 'zebra', 'elephant', 'cat'];
let newAnimals = animals.with(2, 'lion');
newAnimals // ['tiger', 'zebra', 'lion', 'cat']
animals // ['tiger', 'zebra', 'elephant', 'cat']
```

[live code](https://www.codingoals.com/blog/4-new-array-methods) 

These methods are nice improvements that make it easier to work with immutable data 🎉 

As a wrap up, here's joke, cuz why not?

My wife asked me the other day: "Are you even listening to me?"

Which is a really weird way to start a conversation if you ask me.