> Где повесить обработчик клика для кнопок при маппинге массива в React? (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Cyber Interactive

Стек: React

> Пример ответа

Короткий ответ

Обработчик клика для кнопок при маппинге массива в React следует вешать непосредственно на элемент кнопки внутри map, передавая уникальный идентификатор элемента в замыкание. Это стандартный и производительный подход. Избегайте inline-стрелочных функций в JSX без мемоизации, если это не критично для производительности. Для оптимизации используйте useCallback с передачей id.

Подробное объяснение

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

  1. Inline-функция в JSX: onClick={() => handleClick(item.id)} - самый простой, но создаёт новую функцию при каждом рендере. Для большинства случаев это приемлемо, так как React оптимизирует повторные рендеры.

  2. Мемоизированный обработчик с useCallback: если массив большой или компонент часто ререндерится, можно создать обработчик с замыканием на id. Однако useCallback сам по себе не решает проблему создания новых функций - нужно правильно указать зависимости.

  3. Вынос обработчика в отдельный компонент: для сложных списков с анимациями или большим количеством элементов эффективнее создать отдельный компонент для элемента списка и передавать обработчик через props. Это позволяет React точнее управлять ререндерами.

Ключевой момент - обработчик должен иметь доступ к идентификатору или индексу элемента. Никогда не используйте индекс массива как ключ и не полагайтесь на него в обработчике, если массив может изменяться.

На практике

Для типового проекта с формой или списком задач достаточно inline-функции. Для таблиц с сотнями строк или динамических списков с частыми обновлениями - выносите элемент в отдельный компонент с React.memo. Для критичных по производительности случаев используйте data-атрибуты и делегирование событий на родителе, но это редко оправдано в React.

Пример кода

JSX
// Простой случай - inline-функция
function TodoList({ items, onToggle }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>
<button onClick={() => onToggle(item.id)}>
{item.text}
</button>
</li>
))}
</ul>
);
}
// Оптимизированный вариант с отдельным компонентом
const TodoItem = React.memo(({ item, onToggle }) => {
return (
<li>
<button onClick={() => onToggle(item.id)}>
{item.text}
</button>
</li>
);
});
function TodoListOptimized({ items, onToggle }) {
return (
<ul>
{items.map(item => (
<TodoItem key={item.id} item={item} onToggle={onToggle} />
))}
</ul>
);
}

Как отвечать на собеседовании

Начните с прямого ответа - обработчик вешается на кнопку внутри map. Затем поясните trade-off между простотой inline-функции и производительностью мемоизации. Упомяните, что для большинства реальных приложений inline-функция достаточна. Покажите понимание, когда нужна оптимизация: большие списки, частые ререндеры, анимации. Не забудьте про ключи - используйте уникальный id, а не индекс.

Что проверяет интервьюер

Интервьюер оценивает понимание жизненного цикла React-компонентов, механизма ререндеров и оптимизации производительности. Важно показать, что вы умеете выбирать правильный уровень абстракции: не усложнять там, где не нужно, но знать, как оптимизировать при необходимости. Также проверяется знание замыканий и работы с событиями в JSX.

Типичные ошибки

  • Использование индекса массива как ключа и в обработчике - приводит к багам при изменении списка.
  • Передача обработчика без мемоизации в компонент, обёрнутый в React.memo - мемоизация теряет смысл.
  • Создание обработчика с useCallback без правильных зависимостей - ведёт к stale closure.
  • Делегирование событий на контейнере списка через data-атрибуты в React - противоречит декларативному подходу и усложняет код без веской причины.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью