Механизм работы библиотеки основан на перехвате событий ввода
(input, keydown, paste) и
динамическом преобразовании значения поля. Такое поведение неизбежно
пересекается с другими слоями логики приложения: фреймворками,
менеджерами состояния, библиотеками форм и сторонними input-mask
решениями. Основные конфликты возникают не на уровне самой маскировки, а
на уровне конкуренции за контроль над значением поля и курсором.
Конфликты с
фреймворками (React, Vue, Angular)
React:
контролируемые компоненты и потеря синхронизации
В React основная проблема возникает при использовании контролируемых
компонентов, где value полностью управляется
состоянием.
Ключевая конфликтная ситуация:
- Cleave.js изменяет DOM напрямую
- React перезаписывает значение из
state
- происходит «перетягивание каната» между DOM и Virtual DOM
Типичный симптом:
- курсор прыгает в конец строки
- форматирование сбрасывается при каждом вводе
- невозможно ввести промежуточное значение (например, неполный номер
карты)
Причина заключается в том, что Cleave.js модифицирует
input.value вне React-цикла, а React при следующем рендере
возвращает «старое» состояние.
Особенно критично это проявляется при:
- обновлении state на каждый
onChange
- использовании strict mode
- асинхронных обновлениях состояния
Vue: реактивность и
watcher-циклы
Во Vue конфликт возникает через двустороннюю реактивность:
- Cleave.js форматирует значение
v-model тут же реагирует на изменение
- watcher снова форматирует или перезаписывает значение
Возникает цикл:
- ввод символа
- Cleave форматирует
- Vue обновляет модель
- модель перерисовывает input
- Cleave повторно применяет формат
Результат:
- двойное форматирование
- потеря символов
- нестабильный курсор
Особенно проблемно при использовании кастомных директив, где Cleave и
v-model работают одновременно.
В Angular основной конфликт связан с FormControl:
- Cleave.js изменяет DOM напрямую
- Angular ожидает обновления через
ControlValueAccessor
- происходит рассинхронизация модели и view
Симптомы:
dirty/touched состояния обновляются некорректно
- valueChanges срабатывает с уже отформатированным значением
- возможны бесконечные циклы при
setValue
Конфликты с библиотеками
форм
Основная проблема — различие между uncontrolled и controlled
подходом.
- RHF предпочитает uncontrolled inputs
- Cleave.js изменяет DOM value
Конфликтные сценарии:
- register() + Cleave одновременно
- watch() пересоздаёт значение
- reset() теряет форматирование
Частая ошибка — попытка использовать Cleave как обычный input без
адаптера, что приводит к:
- потере фокуса
- повторной инициализации маски
- конфликту refs
Formik полностью контролирует state формы, поэтому Cleave начинает
конкурировать за источник истины.
Проблема:
- Formik хранит «чистое» значение
- Cleave отображает «форматированное»
- при каждом onChange происходит нормализация
Результат:
- значение в UI и state расходятся
- submit отдаёт не тот формат, который виден пользователю
Конфликты с другими масками
ввода
Использование нескольких библиотек маскирования одновременно — один
из самых нестабильных сценариев.
Типичный конфликт:
- Cleave.js
- Inputmask / IMask / custom formatter
Проблема: каждая библиотека перехватывает input и
пытается:
- изменить value
- управлять курсором
- форматировать строку
В результате:
- символы «дёргаются»
- ввод блокируется
- курсор постоянно сбрасывается
Ключевая причина — отсутствие единого ownership над input value.
Наиболее сложный класс конфликтов связан с азиатскими раскладками
(IME: китайский, японский, корейский ввод).
Cleave.js не всегда корректно обрабатывает события composition:
compositionstart
compositionupdate
compositionend
Проблема: во время композиции вводимые символы не являются
финальными, но Cleave может:
- преждевременно форматировать текст
- удалять промежуточные символы
- ломать предсказуемость ввода
Симптомы:
- невозможность набора сложных иероглифов
- сброс текста при подтверждении слова
- потеря курсора внутри композиции
Корректная интеграция требует полного игнорирования форматирования во
время composition-сессии, но это часто реализовано частично или
несовместимо с другими слоями логики.
Конфликты с обработчиками
событий
Если приложение использует собственные обработчики:
- auto-save на
input
- validation pipeline
- analytics tracking
то Cleave.js становится «посредником», который изменяет значение до
того, как его увидят другие обработчики.
Проблемы:
- аналитика получает уже форматированные данные
- валидация работает с изменённым значением
- debounce логика дублирует события
Paste-события
При вставке данных возникает гонка:
- пользователь вставляет значение
- Cleave перехватывает
paste
- браузер вставляет raw value
- Cleave форматирует
- сторонний handler снова читает raw
Результат:
- двойная обработка
- потеря символов
- некорректное форматирование длинных строк
Конфликты с управлением
курсором
Одной из самых чувствительных зон является позиция курсора.
Cleave.js пересчитывает cursor position после каждого
форматирования.
Конфликты возникают, когда:
- внешний код также изменяет selectionStart/selectionEnd
- используется React/Vue rerender
- происходит debounce input
Типичные проблемы:
- курсор прыгает в конец строки
- невозможно редактировать середину значения
- удаление символов работает «скачками»
Конфликты с SSR
(Server-Side Rendering)
При SSR возникает проблема гидратации:
- сервер отдаёт «чистое» значение
- клиент инициализирует Cleave.js и форматирует его
- React/Vue сравнивает DOM и state
Результат:
- hydration mismatch warnings
- мгновенная перерисовка input
- визуальный «флэш» изменения значения
Конфликты при повторной
инициализации
Частая ошибка архитектуры — многократное создание экземпляра Cleave
на одном input.
Сценарии:
- повторный mount компонента
- hot reload в dev-режиме
- условный render
Если старый экземпляр не уничтожен:
- остаются event listeners
- дублируется форматирование
- input обрабатывается несколькими инстансами одновременно
Симптомы:
- двойные разделители (например,
12--34)
- некорректный ввод при быстром наборе
- утечки памяти через listeners
Конфликты с валидацией
и схемами данных
При использовании schema-based validation (Yup, Zod, Joi) возникает
расхождение форматов:
- UI показывает форматированное значение
- схема ожидает «сырое» значение
Cleave.js усложняет разделение этих слоёв.
Типичная ошибка:
- валидация запускается на formatted value
- регулярные выражения перестают совпадать
- сервер получает невалидный формат
Конфликты с
debounce/throttle логикой
При использовании debounce:
- Cleave генерирует много промежуточных изменений
- debounce агрегирует их
- форматирование пересекается с задержкой
Проблемы:
- задержка отображения
- «откат» значения после debounce flush
- расхождение между UI и state
Конфликты с мобильными
клавиатурами
На мобильных устройствах ввод дополнительно усложняется
автокоррекцией и предиктивным вводом.
Сценарии:
- автоисправление изменяет строку после Cleave formatting
- клавиатура вставляет символы пакетно
- Cleave обрабатывает частично обновлённое значение
Результат:
- неожиданные вставки символов
- скачки курсора
- невозможность ввести форматированные числа без ошибок
Архитектурная природа
конфликтов
Все перечисленные проблемы сводятся к одному фундаментальному
противоречию:
- Cleave.js берёт на себя управление представлением значения
- современные фреймворки и form libraries требуют единого источника
истины
Любое пересечение этих двух моделей неизбежно создаёт конкуренцию
за:
- значение input
- событие изменения
- позицию курсора
- момент форматирования