How to Add, Update and Remove an Item from Array in React
Jasser Mark Arioste
Hello, hustler! In this tutorial, you'll learn how to add, insert, update, and remove items from an array using the useState hook in React.
How React Compares Objects #
If you're a beginner in React, it might be a bit confusing to know why your array is not updating when you use the useState hook.
First, we have to understand how React compares objects or values to know when something has changed. React compares objects using the strict equality operator (===) in javascript. Meaning,
Consider the following code:
// this will create a reference to arr1 in memory const arr1 = [1,2,3,4]; // use arr2 to reference arr1; const arr2 = arr1; arr2.push(5); console.log(arr2 === arr1) //true
1234567
Since both arr1
and arr2
share the same reference in memory, meaning they are the same object. Even if we manipulate arr2
, it will still be an "alias" of arr1
in the end. Therefore, if you manipulate the same array, it won't update the state in react.
For example:
import { useState } from "react"; export default function Home() { const [array, setArray] = useState([1, 2, 3, 4]); const addItem = () => { const nextVal = array.length + 1; array.push(nextVal); setArray(array); }; return ( <div> <p>{array.join(",")}</p> <button onClick={addItem}>Add item</button> </div> ); }
12345678910111213141516
In the above code, we try to update the array using array.push
but since the object is still the same exact object in memory, React won't rerender the component.
How to Rerender the Component #
To rerender the component, we have to create a new array that has the same exact elements as our previous array. We can do this by using the spread operator, Array.prototype.concat() method, or Array.prototype.slice(), method. The spread operator is usually the most popular one.
Let's update our example:
import { useState } from "react"; export default function Home() { const [array, setArray] = useState([1, 2, 3, 4]); const addItem = () => { const nextVal = array.length + 1; const arrayCopy = [...array]; //create a copy of the array arrayCopy.push(nextVal); setArray(arrayCopy); // update the state using the copy }; return ( <div> <p>{array.join(",")}</p> <button onClick={addItem}>Add item</button> </div> ); }
1234567891011121314151617
Here, we use the spread operator to create a copy of the array and then we use push to update the contents. A more compact code would be to do the following.
//... const addItem = () => { const nextVal = array.length + 1; // create a copy and add the nextVal as the last element of the array. const arrayCopy = [...array, nextVal]; setArray(arrayCopy); }; //...
12345678
This is an extremely important point when trying to update objects or arrays in React. As long as you create a copy, you can re-render the component. Now that we know the basics, we can easily add, insert, update, or remove an item from an array in React.
Adding an Item to an Array #
Adding an item to an array is pretty much the same as our previous example. You can add an item at the end or r at the start of an array.
import { useState } from "react"; export default function Home() { const [array, setArray] = useState([1, 2, 3, 4]); const addItem = () => { const nextVal = array.length + 1; // add item at the end const arrayCopy = [...array, nextVal]; // add item at the start // const arrayCopy = [nextVal, ...array]; setArray(arrayCopy); }; return ( <div> <p>{array.join(",")}</p> <button onClick={addItem}>Add item</button> </div> ); }
1234567891011121314151617181920
Inserting an Item into an Array #
To insert an item into an array, first, we create a copy of the array using the spread operator and use the splice method. For example:
import React, { useState } from "react"; type Todo = { id: number; title: string; completed?: boolean; }; const InsertItemExample = () => { const [todos, setTodos] = useState<Todo[]>([ { id: 1, title: "Todo1", completed: true, }, { id: 2, title: "Todo2", }, ]); const insertAfter = (id: number, todo: Todo) => { const array = [...todos]; // first, create a copy. // find the index of the id const index = todos.findIndex((todo) => todo.id === id); // use array.splice to insert it at the next index array.splice(index + 1, 0, todo); // update the state setTodos(array); }; return ( <div className="p-10"> {todos.map((todo, i) => { return ( <p key={todo.id} className="p-2"> {i}.) {todo.title} - {todo.completed ? "Completed" : ""} </p> ); })} <button className="p-2 bg-indigo-500 text-white" onClick={() => { insertAfter(1, { title: "Task 2", id: todos.length + 1, completed: false, }); }} > Insert Todo </button> </div> ); }; export default InsertItemExample;
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
Here's the output:
Updating an Item inside an Array #
To update an item inside an array, we can use Array.prototype.map since this also returns a new array. Here's an example:
import React, { useState } from "react"; type Todo = { id: number; title: string; completed?: boolean; }; const UpdateItemExample = () => { const [todos, setTodos] = useState<Todo[]>([ { id: 1, title: "Todo1", completed: true, }, { id: 2, title: "Todo2", }, ]); const updateTodo = (updatedTodo: Todo) => { // map over the todos const updatedArray = todos.map((todo) => { // return the updated todo when we find the same id if (updatedTodo.id === todo.id) { return updatedTodo; } return todo; }); setTodos(updatedArray); }; return ( <div className="p-10"> {todos.map((todo, i) => { return ( <p key={todo.id} className="p-2"> {i}.) {todo.title} - {todo.completed ? "Completed" : ""} </p> ); })} <button className="p-2 bg-indigo-500 text-white" onClick={() => { updateTodo({ id: 2, title: "Updated Todo 3", completed: true, }); }} > Update Todo </button> </div> ); }; export default UpdateItemExample;
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
Here, once the button is clicked, we update the todo with the id:2
with the updated title
and completed
properties.
Here's the output:
Removing an Item from an Array #
To remove an item from an array in React, the best way is still to use Array.prototype.filter in my opinion. This is because it does two things, it returns a new array while filtering the item we want to remove.
Here's an example:
import React, { useState } from "react"; type Todo = { id: number; title: string; completed?: boolean; }; const RemoveItemExample = () => { const [todos, setTodos] = useState<Todo[]>([ { id: 1, title: "Todo1", completed: true, }, { id: 2, title: "Todo2", }, ]); const removeTodo = (idToRemove: number) => { // filter only the todos that doesn't have the id we want to remove const updatedArray = todos.filter((todo) => { return todo.id !== idToRemove; }); setTodos(updatedArray); }; return ( <div className="p-10"> {todos.map((todo, i) => { return ( <div key={todo.id} className="flex gap-2 items-center"> <p className="p-2"> {i}.) {todo.title} - {todo.completed ? "Completed" : ""} </p> <button className="bg-red-300 p-2" onClick={() => removeTodo(todo.id)} > (x) </button> </div> ); })} </div> ); }; export default RemoveItemExample;
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
Here's the output:
That's basically it!
Conclusion #
To update arrays in React, remember that first, we have to create a copy before calling setState
. If the object is the same, it won't re-render the component. There are multiple ways to create new arrays in Javascript such as the spread operator, and array methods such as but not limited to filter(), map(), slice(), and concat().
If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.
Resources #
Credits: Image by Elias Obernosterer from Pixabay