← Назад к вопросам

Как подписаться на событие нажатия на кнопку?

2.0 Middle🔥 181 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Подписка на событие click

Есть несколько способов подписаться на событие нажатия кнопки в JavaScript и React.

1. Ванильный JavaScript

// Способ 1: inline обработчик
<button onclick="handleClick()">Click me</button>

// Способ 2: addEventListener (рекомендуется)
const button = document.getElementById('my-button');
button.addEventListener('click', function(event) {
  console.log('Button clicked!', event);
});

// Способ 3: Присваивание функции
const button = document.querySelector('button');
button.onclick = function() {
  console.log('Clicked');
};

// Способ 4: Стрелочная функция (предпочтительно)
button.addEventListener('click', (event) => {
  console.log('Button clicked:', event.target);
});

2. React - основной способ

// Функциональный компонент - рекомендуется
export function Button() {
  const handleClick = (event) => {
    event.preventDefault();
    console.log('Button clicked!');
  };

  return <button onClick={handleClick}>Click me</button>;
}

// Или через стрелочную функцию прямо в JSX
export function Button() {
  return (
    <button onClick={() => console.log('Clicked')}>
      Click me
    </button>
  );
}

3. React с параметрами

// Передача данных в обработчик
export function Button() {
  const handleClick = (id, event) => {
    console.log('Button ID:', id);
    console.log('Event:', event);
  };

  return (
    <button onClick={(e) => handleClick(123, e)}>
      Click me
    </button>
  );
}

// Или с bind
export function Button() {
  const handleClick = function(id) {
    console.log('ID:', id);
  };

  return (
    <button onClick={handleClick.bind(this, 123)}>
      Click me
    </button>
  );
}

4. Получение информации о событии

export function Button() {
  const handleClick = (event) => {
    console.log('Target:', event.target);           // Элемент
    console.log('Type:', event.type);               // 'click'
    console.log('Timestamp:', event.timeStamp);     // Время
    console.log('Coordinates:', {
      x: event.clientX,
      y: event.clientY
    });
    
    // Остановить распространение события
    event.stopPropagation();
    
    // Отменить поведение по умолчанию
    event.preventDefault();
  };

  return <button onClick={handleClick}>Click me</button>;
}

5. useCallback для оптимизации

import { useCallback } from 'react';

export function ButtonWithCallback() {
  const handleClick = useCallback((event) => {
    console.log('Clicked!');
  }, []);  // Зависимости

  return <button onClick={handleClick}>Click me</button>;
}

// С параметрами
export function ButtonWithParams({ itemId }) {
  const handleClick = useCallback((e) => {
    console.log('Item ID:', itemId);
  }, [itemId]);

  return <button onClick={handleClick}>Click {itemId}</button>;
}

6. Обработчик в пользовательском компоненте

// Компонент Button с prop
interface MyButtonProps {
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  children: React.ReactNode;
}

export function MyButton({ onClick, children }: MyButtonProps) {
  return (
    <button onClick={onClick} className="btn">
      {children}
    </button>
  );
}

// Использование
export function Parent() {
  const handleClick = (event) => {
    console.log('Clicked');
  };

  return <MyButton onClick={handleClick}>Click me</MyButton>;
}

7. Несколько обработчиков на один элемент

export function Button() {
  const handleClick = () => {
    console.log('First handler');
  };

  const handleSecondClick = () => {
    console.log('Second handler');
  };

  const handleMultiple = (event) => {
    handleClick();
    handleSecondClick();
  };

  return (
    <button onClick={handleMultiple}>
      Click me
    </button>
  );
}

8. Типизированный обработчик в TypeScript

import { MouseEvent } from 'react';

interface ButtonProps {
  onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
}

export function Button({ onClick }: ButtonProps) {
  const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {
    event.preventDefault();
    onClick?.(event);
  };

  return <button onClick={handleClick}>Click me</button>;
}

9. Delegation - обработка кликов на нескольких элементах

export function List() {
  const handleListClick = (event: React.MouseEvent) => {
    const target = event.target as HTMLElement;
    
    if (target.tagName === 'BUTTON') {
      const itemId = target.dataset.id;
      console.log('Clicked item:', itemId);
    }
  };

  return (
    <div onClick={handleListClick}>
      <button data-id="1">Item 1</button>
      <button data-id="2">Item 2</button>
      <button data-id="3">Item 3</button>
    </div>
  );
}

Лучшие практики

// ХОРОШО: useCallback с правильными зависимостями
import { useCallback, useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(c => c + 1);  // Функциональное обновление
  }, []);

  return <button onClick={handleClick}>Count: {count}</button>;
}

// ПЛОХО: Функция на каждый рендер
export function BadCounter() {
  const [count, setCount] = useState(0);

  // Новая функция при каждом рендере - неэффективно
  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}

Рекомендуемый подход в React: используй onClick в JSX с useCallback для оптимизации и правильной типизацией в TypeScript.