How to update an array in React + TypeScript
Table of Contents
Introduction
This content is for beginners.
This article briefly provides solutions to a common problem in React: "Why isn't my array update reflected in the UI?"
React + TypeScript: Updating arrays stored in state
I referred to this article. Please see it for detailed explanations.
To cut straight to the chase, in React, direct modification of an array will not be reflected on the screen.
Regardless of the modification to an array, you must create a new array and assign it to the setter.
In JavaScript (and TypeScript), arrays are reference types, so it's natural for changes to also affect the original reference, but React is different. If you want to modify an array, just create a new one and assign it, without any fuss. In some cases, you might end up writing very inefficient (and counter-intuitive) code, but this rule is absolute.
In fact, the same applies not only to arrays but to all reference types, such as object types.
"Create a new one and assign it"
Immutability is key. Believe in it.
Below, I will illustrate with examples of what code to write for adding, deleting, and updating elements in an array.
Adding Elements
push()
is pointless.
Use concat()
or the spread syntax
to generate a new array and assign it to the setter (setArtists).
setArtists([...artists, { id: nextId++, name }]);
Deleting Elements
pop()
, shift()
, and splice()
are all pointless.
Use filter()
or slice()
to generate a new array and assign it to the setter (setArtists).
setArtists(artists.filter(({ id }) => id !== artist.id));
Updating Elements
Modifying array contents using an index is pointless.
Use map()
.
Even when changing a single property of one element in an array of objects, generate a new array and assign it to the setter (setShapes).
const nextShapes = shapes.map((shape) =>
shape.type === 'square'
? {
...shape,
type: 'circle',
color: 'deeppink'
}
: {
...shape,
y: shape.y + 50
}
);
setShapes(nextShapes);
Sorting Arrays
reverse()
and sort()
are pointless and harmful.
Create a copy of the array, then sort it, and assign it to the setter (setList).
const nextList = [...list];
nextList.reverse();
setList(nextList);
Why is it designed this way?
- Advantages
- Bug prevention
- Improved predictability
- Optimized re-rendering
- Time-travel debugging enabled
- Disadvantages
- Code tends to be verbose
- Increased memory usage
- Challenging for beginners
Asking AI will give you many answers.
While the 'bug prevention' aspect is understandable, code verbosity seems unavoidable.
If you're not sure, it's generally accurate to understand immutability as treating reference types like value types. Since updating any value requires calling a setter (and you can simply avoid passing setters to components where you don't want values to be updated), it should be relatively easy to track where values are changed.