Click Outside

В библиотеке Chakra UI управление кликами вне компонента реализуется с помощью хука useOutsideClick. Этот инструмент позволяет отслеживать события клика за пределами указанного элемента и выполнять определённое действие, например, закрытие модального окна, выпадающего меню или тултипа.


Импорт и базовое использование

Для работы с useOutsideClick необходимо импортировать хук из пакета @chakra-ui/react:

import { useRef } from "react";
import { useOutsideClick, Box } from "@chakra-ui/react";

Создание базового элемента с обработкой клика вне:

function Dropdown() {
  const ref = useRef();

  useOutsideClick({
    ref: ref,
    handler: () => {
      console.log("Клик вне элемента");
    },
  });

  return (
    <Box ref={ref} p={4} bg="teal.100" w="200px">
      Контент выпадающего меню
    </Box>
  );
}

Пояснение ключевых моментов:

  • ref – ссылка на DOM-элемент, за пределами которого необходимо отслеживать клики.
  • handler – функция, вызываемая при обнаружении клика вне элемента, на который ссылается ref.
  • Хук автоматически добавляет слушатели событий на mousedown и touchstart, что обеспечивает корректную работу как для мыши, так и для сенсорных устройств.

Использование с модальными окнами

Применение useOutsideClick в сочетании с модальными компонентами позволяет закрывать окно при клике вне области модалки:

import { Modal, ModalContent, ModalOverlay } from "@chakra-ui/react";

function CustomModal({ isOpen, onClose }) {
  const ref = useRef();

  useOutsideClick({
    ref: ref,
    handler: onClose,
  });

  if (!isOpen) return null;

  return (
    <Modal isOpen={isOpen} onCl ose={onClose}>
      <ModalOverlay />
      <ModalContent ref={ref} p={6}>
        Содержимое модального окна
      </ModalContent>
    </Modal>
  );
}

Особенности:

  • ModalContent оборачивается в ref, чтобы useOutsideClick отслеживал именно область модального окна.
  • onClose вызывается только при клике вне модалки, что предотвращает закрытие при взаимодействии с внутренним контентом.

Совмещение с состояниями и анимациями

Часто требуется интеграция с состояниями React для управления видимостью компонентов:

import { useState } from "react";
import { Button, Box } from "@chakra-ui/react";

function Popover() {
  const [isOpen, setIsOpen] = useState(false);
  const ref = useRef();

  useOutsideClick({
    ref: ref,
    handler: () => setIsOpen(false),
  });

  return (
    <Box>
      <Button onCl ick={() => setIsOpen(!isOpen)}>Открыть поповер</Button>
      {isOpen && (
        <Box ref={ref} mt={2} p={4} bg="gray.100" borderRadius="md">
          Содержимое поповера
        </Box>
      )}
    </Box>
  );
}

Ключевые моменты:

  • Управление видимостью через useState позволяет комбинировать useOutsideClick с условным рендерингом.
  • При закрытии компонента через handler состояние обновляется, что автоматически убирает элемент из DOM.

Множественные обработчики и вложенные элементы

Если внутри отслеживаемого компонента есть вложенные интерактивные элементы, важно использовать один ref на общий контейнер, чтобы клики внутри него не вызывали закрытие:

<Box ref={ref} p={4} bg="blue.50">
  <Button onCl ick={() => alert("Внутренний клик")}>Кнопка</Button>
  <Input placeholder="Текстовое поле" mt={2} />
</Box>

useOutsideClick корректно обрабатывает клики на вложенные элементы и не срабатывает, пока клик находится внутри ref.


Советы по оптимизации

  1. Использовать useRef только на элемент-контейнер, а не на каждую внутреннюю часть, чтобы избежать лишних обработчиков.
  2. Минимизировать функции в handler, особенно если они тяжелые, чтобы не снижать производительность при каждом клике.
  3. Комбинировать с useState или useDisclosure, встроенным хук-менеджером Chakra UI для управления состояниями видимости компонентов.
  4. Поддержка мобильных устройств обеспечивается автоматически через обработку событий touchstart.

Альтернатива: useDisclosure

В Chakra UI для компонентов типа Drawer, Modal, Popover часто применяется хук useDisclosure, который в сочетании с useOutsideClick позволяет легко управлять открытием и закрытием элементов. Пример:

import { useDisclosure, Box } from "@chakra-ui/react";

const { isOpen, onOpen, onClose } = useDisclosure();

С этим хуком код становится чище, а логика клика вне компонента интегрируется прямо в состояние isOpen.


Итоговое понимание

Хук useOutsideClick является мощным инструментом для управления интерактивными компонентами в Chakra UI. Он обеспечивает надежное закрытие выпадающих элементов, поповеров и модальных окон, корректно работает с вложенными элементами и мобильными устройствами, а также легко интегрируется с управлением состоянием через React.