Что означают три точки в React? Объясните оператор расширения (spread syntax)
Что такое три точки (spread syntax) в JavaScript?
Три точки ... — это оператор расширения (spread operator), появившийся в ES6 (ES2015). Он позволяет «развернуть» элементы итерируемого объекта (массива, строки, объекта) в места, где ожидается несколько элементов или свойств. В React он используется постоянно для удобной работы с пропсами, состоянием и неизменяемостью данных.
Основные варианты использования
1. Копирование массивов
Вместо создания ссылки (как в вашем примере с arr2 = arr1) используйте spread:
const original = [1, 2, 3];
const copy = [...original]; // Создаётся новый массив
copy.push(4);
console.log(original); // [1, 2, 3] — неизменён
console.log(copy); // [1, 2, 3, 4]
Это поверхностное копирование (shallow copy) — для вложенных объектов нужно быть осторожным.
2. Объединение массивов
const arr1 = [1, 2];
const arr2 = [3, 4];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]
3. Копирование и объединение объектов
const user = { name: 'Alice' };
const details = { age: 25, city: 'Moscow' };
const merged = { ...user, ...details };
// { name: 'Alice', age: 25, city: 'Moscow' }
Важно: если ключи совпадают, последний объект перезаписывает значения:
const a = { x: 1, y: 2 };
const b = { y: 3, z: 4 };
const result = { ...a, ...b }; // { x: 1, y: 3, z: 4 }
4. Добавление/перезапись свойств
const base = { name: 'John', age: 30 };
const updated = { ...base, age: 31, city: 'NY' };
// { name: 'John', age: 31, city: 'NY' }
Как это работает в React?
Передача пропсов
Самый частый кейс — распыление объекта пропсов в JSX:
// Вместо:
<MyComponent name={props.name} age={props.age} city={props.city} />
// Можно:
<MyComponent {...props} />
Это эквивалентно передаче каждого свойства отдельно.
Обновление состояния (useState)
В React важно не мутировать состояние напрямую:
// ❌ НЕПРАВИЛЬНО (мутация):
setUser(user.name = 'Bob');
// ✅ ПРАВИЛЬНО (создаём новый объект):
setUser({ ...user, name: 'Bob' });
Работа с массивами в состоянии
// Добавление элемента:
setItems([...items, newItem]);
// Удаление элемента (по индексу):
setItems(items.filter((_, i) => i !== index));
// Обновление элемента:
setItems(items.map((item, i) =>
i === index ? { ...item, done: true } : item
));
Важные ограничения
- Поверхностное копирование: вложенные объекты копируются по ссылке. Для глубокого копирования используйте
structuredClone()или библиотеки (Immer, Lodash). - Не работает с примитивами:
...5вызовет ошибку, так как число не итерируемо. - Порядок важен: при объединении объектов последний перезаписывает предыдущие одинаковые ключи.
Альтернативы
До ES6 использовали Object.assign():
const merged = Object.assign({}, user, details);
Но spread-синтаксис короче и читаемее.
Итог
Три точки — это мощный инструмент для работы с неизменяемостью данных. В React он помогает обновлять состояние без мутации, удобно передавать пропсы и копировать объекты/массивы. Запомните главное правило: ... создаёт новый объект/массив, а не ссылку на старый.
Дополнение: оператор rest (оставшиеся параметры)
Важно не путать spread-синтаксис с очень похожим, но противоположным по смыслу rest-оператором. Тот же символ ... используется для сбора оставшихся элементов в массив или объект.
Rest в деструктуризации массивов
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
Rest в деструктуризации объектов
const { name, ...details } = { name: 'Alice', age: 25, city: 'Moscow' };
console.log(name); // Alice
console.log(details); // { age: 25, city: 'Moscow' }
Rest в параметрах функции
function sum(...numbers) {
return numbers.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10
Как запомнить разницу?
- Spread — «разворачивает» массив/объект на отдельные элементы (используется при создании новых данных).
- Rest — «собирает» отдельные элементы в массив/объект (используется при получении данных).
Визуально: spread — из одного делает много, rest — из много делает одно.
Практический совет для React
Часто сочетают оба оператора при работе с пропсами:
function MyComponent({ name, ...otherProps }) {
// name — отдельно, остальные пропсы — в otherProps
return <div {...otherProps}>Привет, {name}!</div>;
}
Это позволяет явно выделить нужные пропсы и передать остальные дальше.
Ответов пока нет.
Войдите чтобы оставить ответ