Хук статуса черновика
Легковесный React хук для отслеживания статуса черновика без взаимодействия с DOM.
Обзор
useDraftStatus предоставляет:
- Отслеживание статуса черновика в реальном времени
- Без манипуляций с DOM (только чтение)
- Определение истечения срока
- Возможность ручного обновления
Зачем нужен useDraftStatus?
В отличие от useFormAutosave, useDraftStatus:
- ✅ Не прикрепляется к элементам DOM
- ✅ Не сохраняет и не восстанавливает черновики
- ✅ Только читает из хранилища
- ✅ Идеален для индикаторов статуса, баннеров и UI компонентов
Базовое использование
import { useDraftStatus } from '@form-guardian/react';
function DraftBanner() {
const { hasDraft, updatedAt, isExpired, isChecking } = useDraftStatus('my-form');
if (isChecking) {
return <div>Проверка черновика...</div>;
}
if (!hasDraft) {
return null;
}
if (isExpired) {
return <div>Ваш черновик истек</div>;
}
return (
<div>
Черновик сохранен в {new Date(updatedAt!).toLocaleString()}
</div>
);
}
Справочник API
Параметры
useDraftStatus(formId, options?)
formId(string, обязательный) - Уникальный идентификатор формыoptions(object, опциональный) - Параметры конфигурации
Опции
interface UseDraftStatusOptions {
includeOrigin?: boolean; // Включить origin в ID черновика (по умолчанию: true)
storagePrefix?: string; // Префикс ключа хранилища (по умолчанию: 'fg')
ttl?: number | { // Время жизни для черновиков
days?: number;
hours?: number;
minutes?: number;
};
}
Возвращаемое значение
interface UseDraftStatusResult {
hasDraft: boolean; // Существует ли черновик
isExpired: boolean; // Истек ли черновик
updatedAt: number | null; // Временная метка черновика (если существует)
isChecking: boolean; // Проверяется ли статус
refresh: () => Promise<void>; // Вручную обновить статус
clear: () => Promise<void>; // Очистить черновик из хранилища
}
Примеры
Простой индикатор статуса
import { useDraftStatus } from '@form-guardian/react';
function DraftIndicator() {
const { hasDraft, updatedAt } = useDraftStatus('contact-form');
if (!hasDraft) return null;
return (
<div className="draft-indicator">
💾 Черновик сохранен {new Date(updatedAt!).toLocaleString()}
</div>
);
}
Статус с истечением срока
import { useDraftStatus } from '@form-guardian/react';
function DraftStatus() {
const { hasDraft, isExpired, updatedAt } = useDraftStatus('my-form', {
ttl: { days: 7 },
});
if (!hasDraft) {
return <div>Черновик недоступен</div>;
}
if (isExpired) {
return <div className="expired">⚠️ Черновик истек</div>;
}
return (
<div className="active">
✓ Черновик сохранен {new Date(updatedAt!).toLocaleString()}
</div>
);
}
Ручное обновление
import { useDraftStatus } from '@form-guardian/react';
function DraftStatusWithRefresh() {
const { hasDraft, updatedAt, isChecking, refresh } = useDraftStatus('my-form');
return (
<div>
{isChecking ? (
<span>Проверка...</span>
) : hasDraft ? (
<span>Черновик: {new Date(updatedAt!).toLocaleString()}</span>
) : (
<span>Нет черновика</span>
)}
<button onClick={() => refresh()}>Обновить</button>
</div>
);
}
Очистка черновика
import { useDraftStatus } from '@form-guardian/react';
function DraftControls() {
const { hasDraft, updatedAt, clear } = useDraftStatus('my-form');
const handleClear = async () => {
await clear();
// Черновик теперь очищен
// hasDraft будет false при следующем рендере
};
return (
<div>
{hasDraft && (
<div>
<span>Черновик: {new Date(updatedAt!).toLocaleString()}</span>
<button onClick={handleClear}>Очистить черновик</button>
</div>
)}
</div>
);
}
Случаи использования
1. Баннер черновика
Показать баннер, когда существует черновик:
function DraftBanner() {
const { hasDraft, updatedAt } = useDraftStatus('checkout-form');
if (!hasDraft) return null;
return (
<div className="banner">
У вас есть несохраненный черновик от {new Date(updatedAt!).toLocaleString()}
</div>
);
}
2. Индикатор в навигации
Показать статус черновика в навигации:
function Navigation() {
const { hasDraft } = useDraftStatus('contact-form');
return (
<nav>
<Link href="/contact">Контакты {hasDraft && '💾'}</Link>
</nav>
);
}
3. Статус в заголовке формы
Показать статус в заголовке формы:
function FormHeader() {
const { hasDraft, updatedAt, isExpired } = useDraftStatus('my-form', {
ttl: { days: 7 },
});
return (
<header>
<h1>Моя форма</h1>
{hasDraft && (
<div className="status">
{isExpired ? (
<span className="expired">Черновик истек</span>
) : (
<span>Последнее сохранение: {new Date(updatedAt!).toLocaleString()}</span>
)}
</div>
)}
</header>
);
}
4. Несколько форм
Отслеживание статуса для нескольких форм:
function MultiFormStatus() {
const contactStatus = useDraftStatus('contact-form');
const checkoutStatus = useDraftStatus('checkout-form');
return (
<div>
<div>Контакты: {contactStatus.hasDraft ? '💾' : '✗'}</div>
<div>Оформление: {checkoutStatus.hasDraft ? '💾' : '✗'}</div>
</div>
);
}
Лучшие практики
1. Согласованная конфигурация
При использовании с useFormAutosave, сопоставьте конфигурацию:
// useFormAutosave
const { formRef } = useFormAutosave('my-form', {
includeOrigin: true,
storagePrefix: 'fg',
ttl: { days: 7 },
});
// useDraftStatus (должны совпадать)
const { hasDraft } = useDraftStatus('my-form', {
includeOrigin: true, // Должно совпадать
storagePrefix: 'fg', // Должно совпадать
ttl: { days: 7 }, // Должно совпадать
});
2. Обработка состояния загрузки
const { hasDraft, isChecking } = useDraftStatus('my-form');
if (isChecking) {
return <Skeleton />; // Показать состояние загрузки
}
// Отрисовать фактический контент
Производительность
- Легковесный - Без манипуляций с DOM, только чтение из хранилища
- Эффективный - Читает только когда нужно
- Кэшированный - Статус кэшируется до обновления или широковещательного обновления
- Безопасный для SSR - Возвращает безопасные значения по умолчанию на сервере
Следующие шаги
- 📖 Справочник API - Полная документация API
- ⚙️ Пакетная обработка - Оптимизация производительности сохранения
- 📊 События аналитики - Отслеживание взаимодействий с формой