Flatpickr создаёт инстансы календаря, которые связываются с DOM-элементами, событиями и внутренними структурами состояния. В типичных сценариях браузер самостоятельно очищает память при удалении DOM-узлов, однако при наличии активных ссылок, подписок на события и замыканий сборщик мусора не может освободить объекты. Это приводит к постепенному росту потребления памяти, особенно в SPA-приложениях, где компоненты часто монтируются и размонтируются.
Основной источник проблем связан не с самой библиотекой, а с неправильным жизненным циклом экземпляра календаря.
Каждый вызов flatpickr() создаёт объект инстанса,
содержащий:
При этом инстанс регистрирует обработчики на document и window, что делает его живым даже при удалении исходного элемента из DOM.
Наиболее частая проблема — уничтожение DOM без освобождения инстанса.
const fp = flatpickr("#date", {});
document.querySelector("#date").remove();
В этом случае элемент исчезает из DOM, но:
Корректное завершение жизненного цикла требует явного вызова:
fp.destroy();
destroy() удаляет DOM календаря, снимает все события и
разрывает внутренние ссылки.
Утечки часто возникают при сохранении инстанса в замыкании или глобальном хранилище:
function createPicker() {
const fp = flatpickr("#date", {});
return function getValue() {
return fp.selectedDates;
};
}
Функция getValue удерживает ссылку на fp, а
значит весь объект календаря остаётся в памяти даже после удаления
input.
В React, Vue или аналогичных системах при неправильной интеграции создаются новые экземпляры Flatpickr при каждом рендере компонента.
Типичный анти-паттерн:
useEffect(() => {
flatpickr(inputRef.current, {});
});
Каждый рендер создаёт новый календарь без уничтожения предыдущего. Это приводит к:
При повторном использовании DOM-узлов библиотека может повторно привязать события, если старый инстанс не был уничтожен. Это создаёт эффект “двойных кликов” и увеличивает количество активных listener-ов.
Flatpickr создаёт элементы календаря вне основного контейнера input (обычно в body). Если инстанс не уничтожен, эти элементы продолжают существовать в DOM:
Flatpickr активно использует глобальные события:
Если обработчики не удаляются, они продолжают вызываться даже после удаления UI, удерживая контекст инстанса.
Повторный вызов flatpickr() на одном и том же элементе
без уничтожения старого экземпляра приводит к наложению инстансов:
flatpickr("#date", {});
flatpickr("#date", {});
Последствия:
При создании элементов через innerHTML и последующей инициализации Flatpickr часто теряется контроль над предыдущими экземплярами:
container.innerHTML = `<input id="date">`;
flatpickr("#date", {});
При повторном обновлении контейнера старый input исчезает из DOM, но инстанс календаря может остаться в памяти, если не был уничтожен явно.
Flatpickr позволяет подключать кастомные плагины и обработчики:
Если внутри callback создаются внешние ссылки (например, на store или сервис), они могут удерживать инстанс даже после уничтожения DOM.
flatpickr("#date", {
onChange: (selectedDates) => {
globalStore.lastDate = selectedDates[0];
}
});
Если globalStore хранит ссылки на инстансы, сборщик
мусора не освобождает память.
Корректное завершение жизненного цикла включает несколько операций:
fp.destroy();
fp = null;
Обнуление переменной дополнительно снимает последнюю сильную ссылку.
В системах с виртуальным DOM (React, Vue) DOM-узлы могут переиспользоваться. Flatpickr при этом может не осознавать, что элемент был заменён логически, но не физически. Это приводит к ситуации:
Использование глобальных переменных для хранения инстансов приводит к накоплению объектов:
window.pickers.push(flatpickr("#date", {}));
Без очистки массива pickers все инстансы остаются в
памяти, даже при удалении UI.
Flatpickr часто используется внутри модалок. При закрытии модалки DOM может быть удалён, но:
Это особенно заметно при повторном открытии модального окна.
Управление жизненным циклом требует централизованного хранения ссылок:
В противном случае количество активных календарей растёт линейно с количеством рендеров.
Типичные признаки:
Инструменты разработчика позволяют отслеживать:
Garbage Collector в браузере освобождает память только при отсутствии сильных ссылок. Flatpickr-инстанс считается живым, пока:
Любая из этих связей блокирует освобождение памяти.