Як оновити елемент масиву у стані?
Головна ідея
У React стан повинен бути іммутабельним -
не можна змінювати масив напряму (push, splice, присвоєння за index).
Замість цього потрібно створити новий масив з потрібними змінами
і передати його в setState.
Приклад 1. Оновлення елемента за індексом
javascript
function App() {
const [numbers, setNumbers] = useState([10, 20, 30]);
const updateSecond = () => {
setNumbers(prev =>
prev.map((num, i) => (i === 1 ? num + 5 : num))
);
};
return (
<div>
<p>{numbers.join(", ")}</p>
<button onClick={updateSecond}>Змінити другий елемент</button>
</div>
);
}map() створює новий масив
Ми змінюємо тільки той елемент, де i === 1
Решта залишаються без змін
Результат:
javascript
[10, 20, 30] → [10, 25, 30]Приклад 2. Оновлення за умовою (наприклад, за id)
Дуже часто в стані зберігаються об'єкти:
javascript
const [users, setUsers] = useState([
{ id: 1, name: "Alex", active: false },
{ id: 2, name: "Tim", active: true },
]);Хочеш оновити конкретного користувача:
javascript
const toggleActive = (id) => {
setUsers(prev =>
prev.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};Що відбувається:
map()створює новий масив- якщо id збігається -> створюємо новий об'єкт (іммутабельно)
- інакше повертаємо старий об'єкт
Приклад 3. Оновлення за індексом (варіант з копією масиву)
Можна зробити вручну:
javascript
const [items, setItems] = useState(["яблуко", "банан", "вишня"]);
const changeBanana = () => {
const copy = [...items]; // створюємо копію
copy[1] = "манго"; // змінюємо елемент у копії
setItems(copy); // оновлюємо стан
};Ніколи не роби так:
javascript
items[1] = "манго"; // мутує масив
setItems(items); // React не помітить змінПриклад 4. Оновлення вкладеного масиву в об'єкті
javascript
const [cart, setCart] = useState({
items: [
{ id: 1, name: "Сорочка", qty: 1 },
{ id: 2, name: "Штани", qty: 2 },
],
});
const incrementQty = (id) => {
setCart(prev => ({
...prev,
items: prev.items.map(item =>
item.id === id ? { ...item, qty: item.qty + 1 } : item
),
}));
};Тут:
- ми копіюємо об'єкт
cart(...prev) - всередині оновлюємо масив
itemsіммутабельно черезmap()
5. Коли використовувати який спосіб
| Завдання | Підхід |
|---|---|
| Змінити за індексом | map() або копія з [...arr] |
Змінити за id | map() з умовою |
| Оновити вкладений об'єкт | Копіювати і зовнішній, і внутрішній рівні |
| Додати елемент | [...arr, newItem] |
| Видалити елемент | arr.filter(...) |
Підсумок
| Що не можна робити | Що потрібно робити |
|---|---|
array[index] = value | setArray(prev => prev.map(...)) |
array.push(value) | setArray(prev => [...prev, value]) |
array.splice(i,1) | setArray(prev => prev.filter(...)) |
array.sort() | setArray(prev => [...prev].sort(...)) |
Запам'ятай
Ніколи не мутуй масив стану напряму. Завжди створюй новий масив або об'єкт. React порівнює посилання, а не вміст. Використовуй
map(),filter(),slice(), spread (...).
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.