> Как реализовать добавление и удаление кнопок с уникальными id в React при кликах (React, JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Kaspersky
Стек: React, JavaScript
> Пример ответа
Короткий ответ
Для добавления и удаления кнопок с уникальными id в React при кликах используйте состояние (useState) с массивом объектов, где каждый объект содержит id и другие данные. При клике на "добавить" генерируйте новый id (например, с помощью Date.now() или crypto.randomUUID()) и добавляйте элемент в массив. При клике на "удалить" фильтруйте массив по id. Обязательно используйте id как key при рендеринге списка.
Подробное объяснение
Управление динамическим списком кнопок в React требует правильной работы с состоянием и ключами. Основная сложность - гарантировать уникальность id и эффективно обновлять UI при добавлении/удалении.
Генерация уникальных id: для простых случаев подходит Date.now(), но в production лучше использовать crypto.randomUUID() (современные браузеры) или библиотеку вроде uuid. Id не должны меняться между рендерами, иначе React будет пересоздавать DOM-элементы.
Работа с состоянием: используйте функциональную форму setState, чтобы избежать race conditions при быстрых кликах. При добавлении создавайте новый массив через spread-оператор, при удалении - через filter.
Ключи (keys): всегда используйте id как key для элементов списка. Это позволяет React эффективно обновлять только изменившиеся элементы, а не перерисовывать весь список.
Производительность: для больших списков (сотни+ элементов) рассмотрите виртуализацию (react-window). Для частых операций удаления/добавления используйте useMemo для стабильных ссылок на функции-обработчики.
На практике
В реальных проектах часто требуется не просто список кнопок, а управление их состоянием (активна/неактивна, текст, стили). Храните все данные в объекте внутри массива:
JAVASCRIPTconst [buttons, setButtons] = useState([]);// Каждый элемент: { id: 'abc123', label: 'Кнопка 1', isActive: false }
При удалении важно передавать правильный id - обычно через замыкание в колбэке или data-атрибут. Избегайте использования индекса массива как id - это приводит к багам при удалении элементов из середины списка.
Для анимаций добавления/удаления используйте библиотеки вроде react-spring или framer-motion с AnimatePresence - они корректно работают с React-ключами.
Пример кода
JSXimport React, { useState, useCallback } from 'react';const ButtonManager = () => {const [buttons, setButtons] = useState([]);const addButton = useCallback(() => {const newButton = {id: crypto.randomUUID(),label: `Кнопка ${buttons.length + 1}`,timestamp: Date.now()};setButtons(prev => [...prev, newButton]);}, [buttons.length]);const removeButton = useCallback((idToRemove) => {setButtons(prev => prev.filter(btn => btn.id !== idToRemove));}, []);return (<div><button onClick={addButton}>Добавить кнопку</button><div>{buttons.map(btn => (<buttonkey={btn.id}onClick={() => removeButton(btn.id)}style={{ margin: '4px' }}>{btn.label} ✕</button>))}</div></div>);};
Как отвечать на собеседовании
Начните с ключевого принципа: состояние как единственный источник правды. Объясните, почему id должен быть уникальным и стабильным - это критично для React reconciliation. Упомяните, что используете функциональное обновление состояния для потокобезопасности.
Покажите понимание trade-off: crypto.randomUUID() vs Date.now() vs библиотеки. Для senior-уровня важно упомянуть edge cases: что если id закончатся (теоретически), как обрабатывать дубликаты, как тестировать такие компоненты.
Завершите практическим советом: всегда передавайте id через замыкание в обработчик, а не через data-атрибут, если не требуется доступ к DOM.
Что проверяет интервьюер
- Понимание React-состояния и иммутабельности
- Знание механизма ключей (keys) и reconciliation
- Умение работать с асинхронностью setState
- Способность предусмотреть edge cases (быстрые клики, удаление последнего элемента)
- Понимание разницы между id и index как key
- Знание современных API (crypto.randomUUID)
Типичные ошибки
- Использование индекса массива как key - приводит к багам при удалении/пересортировке
- Мутация состояния напрямую (push вместо spread)
- Генерация id внутри render без useMemo/useCallback - каждый рендер создаёт новый id
- Отсутствие функциональной формы setState при быстрых кликах
- Хранение id в состоянии, которое можно вычислить (derived state)
- Использование Math.random() для id - не гарантирует уникальность в распределённых системах
> Похожие задачи по frontend
Как заставить useSWR отрабатывать только на клиенте, пропуская сервер
Как обработать ошибки в React приложении
Как реализовать кастомный хук для отслеживания первого рендера в React?
Для чего нужен React.lazy
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью