Средство выбора даты без заголовка для приложений React

Средство выбора даты без заголовка для приложений React

24 декабря 2022 г.

С каждым годом сообщество ⚛️ React становится все больше и больше.

И с этим ростом мы получаем все больше и больше инструментов для достижения наших целей и потребностей. Несмотря на это невероятное разнообразие, трудно получить то, что вы хотите.

Проблема

Давайте углубимся в проблему:

  • 🙅 в вашей библиотеке компонентов нет нужного компонента;
  • ⚙️ вам необходимо внести изменения в процесс сборки;
  • 💅 ваша система укладки отличается от самого популярного решения;
  • 🦹 сложно настроить компонент, соответствующий вашему дизайну;
  • 💰 получение необходимых компонентов может стоить денег (привет MUI 😉)
  • 🏋️ библиотека тяжёлая и не имеет tree-shaking;
  • 📚 ужасная документация;
  • ⛔️ без тестов, без поддержки TypeScript, без примеров...

И это всего лишь выбор даты 🗓.

Решение

Решением всех этих 👆 проблем может быть компонент безголового пользовательского интерфейса, такой как @rehookify/datepicker

Основные функции и преимущества:

  • маленький размер
  • ноль зависимостей;
  • модульный дизайн позволяет использовать как можно меньше кода;
  • одиночный, множественный выбор и диапазон даты;
  • поддержка нескольких календарей;
  • поддерживать нативную локализацию с помощью .toLocaleDateString;
  • prop-getters, чтобы предоставить все необходимые реквизиты для ваших компонентов;

Главный недостаток в том, что вам нужно стилизовать все самостоятельно. Но с современными методами компоновки CSS, такими как grid и flex, это сделать легко и весело. Значит недостатков нет вообще 😅

Используя @rehookify/datepicker, вы можете выбрать модульный или комплексный подход.

Код

Модульные крючки

В приведенном ниже примере показан календарь с несколькими вариантами дат 👇

import {
  useDatePickerState,
  useDaysPropGetters,
} from '@rehookify/datepicker';

const DatePicker = () => {
  const config = { dates: { toggle: true, mode: 'multiple' }}
  const [state, dispatch] = useDatePickerState(config);
  const { calendars, weekDays } = useCalendars(state);
  const { dayButton } = useDaysPropGetters(state, dispatch);

  const { month, year, days } = calendars[0];

  return (
    <section>
      <header>
        <div>
          <p>{month} {year}</p>
        </div>
        <ul>
          {weekDays.map((day) => (
            <li key={`${month}-${day}`}}>{day}</li>
          ))}
        </ul>
      </header>
      <ul>
        {days.map((dpDay) => (
          <li
            key={`${month}-${dpDay.date}`} 
          >
            <button {...dayButton(dpDay)}>{dpDay.day}</button>
          </li>
        ))}
      </ul>
    </section>
  );
}

Модульный контекст

Если вы не хотите передавать какие-либо параметры 💆‍♂️ или хотите разделить компоненты, вы можете использовать реализацию контекста.

В приведенном ниже примере показан календарь с выбором диапазона дат 👇

import {
  DatePickerStateProvider,
  useContextCalendars,
  useContextDaysPropGetters,
} from '@rehookify/datepicker';

const DatePicker = () => {
  const { calendars, weekDays } = useContextCalendars();
  const { dayButtons } = useContextDaysPropGetters();

  const { year, month, days } = calendars[0];

  return (
    <section>
      <header>
        <div>
          <p>{month} {year}</p>
        </div>
        <ul>
          {weekDays.map((day) => (
            <li key={`${month}-${day}`}>{day}</li>
          ))}
        </ul>
      </header>
      <ul>
        {days.map((dpDay) => (
          <li
            key={`${month}-${dpDay.date}`}
          >
            <button
              {...dayButton(dpDay)}
              disabled={dpDay.disabled}
            >{dpDay.day}</button>
          </li>
        ))}
      </ul>
    </section>
  )
}

const App = () => {
  <DatePickerStateProvider
    config={{ dates: { mode: 'range' }}}
  >
    <DatePicker />
  </DatePickerStateProvider>
}

Универсальные решения

использовать средство выбора даты

Календарь с выбором даты и разбивкой по месяцам 👇

import React, { MouseEvent } from 'react';
import { useDatePicker } from '@rehookify/datepicker';

const DatePicker = () => {
  const {
    data: { weekDays, calendars, formattedDates },
    propGetters: {
      dayButton,
      previousMonthButton,
      nextMonthButton,
    },
  } = useDatePicker();

  // calendars[0] is always present, this is an initial calendar
  const { year, month, days } = calendars[0];

  const onDayClick = (evt: MouseEvent<HTMLElement>, date: Date) => {
    // In case you need any action with the event
    evt.stopPropagation();

    // In case you need any additional action with date
    console.log(date);
  }

  // formattedDates is an array of dates formatted with
  // `.toLocaleDateString(locale, options)`
  return (
    <section>
      {selectedDates.length > 0 && <h1>{formattedDates[0]}</h1>}
      <header>
        <div>
          <button {...previousMonthButton()}>&lt;</button>
          <p>{month} {year}</p>
          <button {...nextMonthButton()}>&gt;</button>
        </div>
        <ul>
          {weekDays.map((day) => (
            <li key={`${month}-${day}`}>{day}</li>
          ))}
        </ul>
      </header>
      <ul>
        {days.map((dpDay) => (
          <li key={dpDay.date}>
            <button {...dayButton(dpDay)}>{dpDay.day}</button>
          </li>
        ))}
      </ul>
    </section>
  )
}

Провайдер выбора даты

import {
  DatePickerProvider,
  useDatePickerContext,
} from '@rehookify/datepicker';

const DatePicker = () => {
  const {
    data: { weekDays, calendars, years, months }
  } = useDatePickerContext();

  const { year, month, days } = calendars[0];

  return (
    <section>
      <header>{month} {year}</header>
      ...
    </section>
  )
}

const App = () => {
  <DatePickerProvider config={{ dates: { mode: 'range' }}}>
    <DatePicker />
  </DatePickerProvider>
}

Заключение

@rehookify/datepicker поможет вам создать средство выбора даты, которое соответствует вашим потребностям и техническому стеку. Его модульная конструкция позволит сохранить как можно больше байтов для вашего приложения.

Изображение Антона Лапко


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE