Реактивность массивов в React


Массивы в React также обладают реактивностью. При чем React реактивно реагирует на все изменения массива: на добавление, удаление, изменение элементов, а также на изменение их порядка.

При этом правилами React запрещено изменять сам массив из стейта, он должен быть иммутабельным. Правильным подходом в React является создание нового массива на основе предыдущего и перезапись стейта новым массивом.

Давайте посмотрим, как это осуществляется на практике. Пусть в стейте notes хранится массив:

function App() {
const [notes, setNotes] = useState([1, 2, 3, 4, 5]);

return <div>

</div>;
}
Давайте выведем каждый элемент этого массива в отдельном абзаце:

function App() {
const [notes, setNotes] = useState([1, 2, 3, 4, 5]);

const result = notes.map((note, index) => {
return <p key={index}>{note}</p>;
});

return <div>
{result}
</div>;
}
Добавление
Давайте добавим в наш массив notes еще один элемент. Через метод push это делать неправильно, так как мы изменяем сам массив:

notes.push(6); // так не правильно
setNotes(notes);
Чтобы не изменять сам массив, можно сделать его копию, применить к ней метод push, и затем перезаписать стейт на массив из копии:

const copy = Object.assign([], notes);
copy.push(6); // так правильно
setNotes(copy);
А можно использовать хитрый прием с деструктуризацией:

setNotes([...notes, 6]); // так правильно

Удаление
Давайте удалим из массива элемент по его номеру. Пусть этот номер хранится в переменной index. Через метод splice удаление делать неправильно, так как изменятся массив:

notes.splice(index, 1); // так не правильно
setNotes(notes);
Однако, можно применить splice к копии массива:

const copy = Object.assign([], notes);
copy.splice(index, 1); // так правильно
setNotes(copy);
Либо использовать деструктуризацию следующим образом:

setNotes([...notes.slice(0, index), ...notes.slice(index + 1)]);

Изменение
Пусть мы хотим поменять значение некоторому элементу массива. Пусть номер для изменения хранится в переменной index.

Изменять элемент напрямую будет неправильно:

notes[index] = '!'; // так не правильно
setNotes(notes);
Правильным подходом будет изменить его копию:

let copy = Object.assign([], notes);
copy[index] = '!'; // так правильно
setNotes(copy);
Либо использовать деструктуризацию:

setNotes([...notes.slice(0, index), '!',...notes.slice(index + 1)]);

Сортировка и переворот
Сортировать массив также будет неправильным, так как функция сортировки изменяет массив:

notes.sort(); // так не правильно
setNotes(notes);
Правильным подходом будет выполнить сортировку копии:

let copy = Object.assign([], notes);
copy.sort(); // так правильно
setNotes(copy);