useCheckbox для одиночных чекбоксов

useCheckbox — это хук из библиотеки React Aria, предназначенный для управления состоянием и поведением одиночного чекбокса с полной поддержкой доступности (accessibility). Он обеспечивает правильное управление фокусом, клавиатурными событиями и ARIA-атрибутами без необходимости ручного вмешательства.


Основные возможности

  • Управление состоянием чекбокса: хук возвращает объект состояния, который можно использовать для отслеживания состояния checked, disabled и indeterminate.
  • Генерация необходимых ARIA-атрибутов: автоматически добавляет aria-checked, aria-disabled и другие атрибуты, необходимые для доступности.
  • Совместимость с формами: корректно интегрируется с формами, поддерживая стандартные события onChange.
  • Поддержка клавиатурных взаимодействий: обеспечивает работу пробелом для переключения состояния и навигацию с помощью табуляции.

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

import { useCheckbox } from '@react-aria/checkbox';
import { useToggleState } from '@react-stately/toggle';

function CheckboxExample() {
  const state = useToggleState();
  const ref = React.useRef();
  const { inputProps } = useCheckbox({ isSelected: state.isSelected, onChange: state.toggle }, state, ref);

  return (
    <label>
      <input {...inputProps} ref={ref} />
      Согласен с условиями
    </label>
  );
}
  • useToggleState предоставляет управляемое состояние isSelected и метод toggle.

  • useCheckbox принимает объект пропсов с ключевыми свойствами:

    • isSelected — текущее состояние чекбокса (true/false).
    • onChange — функция, вызываемая при изменении состояния.
    • isDisabled (необязательный) — делает чекбокс недоступным.
    • isIndeterminate (необязательный) — позволяет создать промежуточное состояние.

Пропсы и их использование

Проп Тип Назначение
isSelected boolean Определяет, отмечен ли чекбокс
onChange function Обработчик изменения состояния
isDisabled boolean Блокирует взаимодействие с чекбоксом
isIndeterminate boolean Отображает промежуточное состояние (например, для “выбрать все”)
name string Имя чекбокса для формы
value string Значение чекбокса при отправке формы

Управление состоянием

useCheckbox тесно интегрируется с useToggleState, который управляет состоянием выбора:

const state = useToggleState({ defaultSelected: true });
console.log(state.isSelected); // true или false
state.toggle(); // меняет состояние

При использовании хука:

  • Состояние checked синхронизируется с isSelected.
  • Состояние indeterminate отражается в inputProps через aria-checked="mixed".

Доступность

Для одиночного чекбокса useCheckbox обеспечивает:

  1. ARIA-атрибуты:

    • aria-checked принимает значения true, false или mixed.
    • aria-disabled устанавливается автоматически, если передан isDisabled.
  2. Keyboard support:

    • Пробел переключает состояние.
    • Tab позволяет перемещаться между чекбоксами или другими интерактивными элементами.
  3. Label association: хук не привязывает label напрямую, но возвращаемые inputProps можно передать стандартному <input> внутри <label>.


Пример с индетерминированным состоянием

function ParentCheckbox() {
  const state = useToggleState();
  const ref = React.useRef();
  const { inputProps } = useCheckbox({ isSelected: state.isSelected, isIndeterminate: true, onChange: state.toggle }, state, ref);

  return (
    <label>
      <input {...inputProps} ref={ref} />
      Частично выбрано
    </label>
  );
}
  • isIndeterminate: true создаёт состояние “частично выбран”.
  • ARIA автоматически отражает это как aria-checked="mixed".

Работа с формами

Чекбокс интегрируется в формы, сохраняя привычный API:

<form onSub mit={handleSubmit}>
  <CheckboxExample name="terms" value="agree" />
  <button type="submit">Отправить</button>
</form>
  • Значение чекбокса будет отправлено как часть формы, если он отмечен.
  • useCheckbox не мешает стандартным событиям onChange и onSubmit.

Расширение для кастомного UI

Часто требуется стилизовать чекбокс под дизайн системы. useCheckbox позволяет это без потери доступности:

function StyledCheckbox() {
  const state = useToggleState();
  const ref = React.useRef();
  const { inputProps } = useCheckbox({ isSelected: state.isSelected, onChange: state.toggle }, state, ref);

  return (
    <div className="custom-checkbox" onCl ick={state.toggle}>
      <input {...inputProps} ref={ref} className="hidden" />
      <span className={state.isSelected ? 'checked' : ''}></span>
    </div>
  );
}
  • Чекбокс <input> скрыт через CSS, но доступность сохраняется.
  • Клик по кастомному элементу вызывает state.toggle, синхронизируя состояние.

Рекомендации по использованию

  • Использовать useToggleState для управления состоянием — это упрощает синхронизацию с другими компонентами.
  • Всегда передавать ref в input для корректного фокусирования.
  • Для групп чекбоксов использовать useCheckboxGroup, а для одиночных — useCheckbox.
  • Индетерминированное состояние подходит для частично выбранных элементов, например, при выборе всех подопечных опций.

Эта комбинация хуков позволяет создавать полностью доступные, управляемые одиночные чекбоксы с минимальными усилиями и полной поддержкой современных стандартов ARIA.