Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як оновити елемент масиву у стані?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)У React стан **повинен бути іммутабельним**, тому не можна змінювати масив напряму (`push`, `splice`, присвоєння за індексом) - замість цього потрібно створити **новий масив** з потрібними змінами і передати його в `setState`. **Ключове:** React порівнює **посилання**, а не вміст, тому оновлення завжди роблять через `map()`, `filter()`, `slice()` або spread (`...`).Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Головна ідея У 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 (`...`).Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.