Перейти к основному содержимому

Лучшие практики и подводные камни

Это руководство охватывает лучшие практики использования Form Guardian и распространенные подводные камни, которых следует избегать.

Лучшие практики

Оптимизируйте размер данных

Не сохраняйте большие объекты без необходимости:

// ❌ Неправильно - сохраняет весь большой объект
const { formRef } = useFormAutosave('form', {
autoRestore: true,
});
// Форма содержит большие base64 изображения, огромные JSON объекты и т.д.

// ✅ Правильно - исключите большие поля
const { formRef } = useFormAutosave('form', {
autoRestore: true,
blacklist: [
'input[name="large-image"]',
'textarea[name="huge-json"]',
],
});

Установите подходящий TTL

Используйте подходящее время жизни в зависимости от вашего случая использования:

// Короткие формы (контакт, обратная связь)
ttl: { hours: 24 }

// Средние формы (заявки, опросы)
ttl: { days: 7 }

// Длинные формы (черновики, сочинения)
ttl: { days: 30 }

Очищайте черновики после отправки

Всегда очищайте черновики после успешной отправки:

const handleSubmit = async (data) => {
try {
await submitForm(data);
await clearDraft(); // ✅ Очистите после успеха
} catch (error) {
// Сохраните черновик, если отправка не удалась
console.error('Отправка не удалась, черновик сохранен');
}
};

Обрабатывайте ошибки изящно

const { formRef, restoreDraft } = useFormAutosave('form', {
autoRestore: false,
onRestore: (error) => {
if (error) {
console.error('Не удалось восстановить черновик:', error);
// Покажите пользователю дружественное сообщение
}
},
});

Распространенные подводные камни

Подводный камень 1: Не отключать автосохранение во время отправки

Проблема: Автосохранение может сработать во время отправки формы, вызывая race conditions.

// ❌ Неправильно - автосохранение может сработать во время отправки
const handleSubmit = async (e) => {
e.preventDefault();
await submitForm();
await clearDraft();
};

Решение: Отключите автосохранение во время отправки:

// ✅ Правильно - отключите автосохранение во время отправки
const [isSubmitting, setIsSubmitting] = useState(false);
const { formRef, clearDraft, destroy } = useFormAutosave('form', {
autoRestore: true,
});

const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
destroy(); // Остановить автосохранение

try {
await submitForm();
await clearDraft();
} catch (error) {
console.error('Ошибка отправки');
} finally {
setIsSubmitting(false);
}
};

Подводный камень 2: Игнорирование TTL

Проблема: Черновики накапливаются в IndexedDB без истечения срока.

// ❌ Неправильно - черновики никогда не истекают
const { formRef } = useFormAutosave('form');

Решение: Всегда устанавливайте подходящий TTL:

// ✅ Правильно - черновики автоматически истекают
const { formRef } = useFormAutosave('form', {
ttl: { days: 7 },
});

Подводный камень 3: Сохранение чувствительных данных

Проблема: Сохранение паролей или токенов в локальном хранилище.

// ❌ Неправильно - может сохранить пароли
<form>
<input name="username" />
<input name="password" type="password" /> {/* Автоматически исключено */}
<input name="api-key" type="text" /> {/* Не автоматически исключено! */}
</form>

Решение: Используйте blacklist для чувствительных полей:

// ✅ Правильно - явно исключите чувствительные поля
const { formRef } = useFormAutosave('form', {
blacklist: [
'input[name="api-key"]',
'input[name="secret"]',
'input[name="token"]',
],
});

Подводный камень 4: Не проверять наличие черновика перед отправкой

Проблема: Пользователь может случайно отправить старые данные.

// ❌ Неправильно - может отправить устаревшие данные
const handleSubmit = async (e) => {
e.preventDefault();
await submitForm();
};

Решение: Проверьте наличие черновика и предупредите пользователя:

// ✅ Правильно - проверьте черновик перед отправкой
const { hasDraft, draftTimestamp } = useFormAutosave('form');

const handleSubmit = async (e) => {
e.preventDefault();

if (hasDraft) {
const shouldProceed = confirm(
`У вас есть несохраненный черновик от ${new Date(draftTimestamp).toLocaleString()}. Продолжить?`
);
if (!shouldProceed) return;
}

await submitForm();
};

Подводный камень 5: Не использовать debounce

Проблема: Слишком частые сохранения влияют на производительность.

// ❌ Неправильно - сохраняет при каждом нажатии клавиши
const { formRef } = useFormAutosave('form', {
debounceMs: 0,
});

Решение: Используйте подходящую задержку debounce:

// ✅ Правильно - оптимизированная задержка debounce
const { formRef } = useFormAutosave('form', {
debounceMs: 500, // Сохранять через 500мс после прекращения набора
});

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

Используйте пакетное сохранение для больших форм

const { formRef } = useFormAutosave('large-form', {
batchSaveInterval: 2000, // Сохранять изменения каждые 2 секунды
});

Используйте useDraftStatus для индикаторов

// ✅ Легковесный - не подписывается на изменения формы
import { useDraftStatus } from '@form-guardian/react';

function DraftIndicator() {
const { hasDraft, timestamp } = useDraftStatus('my-form');

if (!hasDraft) return null;
return <div>Последнее сохранение: {new Date(timestamp).toLocaleString()}</div>;
}

Безопасность

Никогда не сохраняйте:

  • ❌ Пароли
  • ❌ Номера кредитных карт
  • ❌ Номера социального страхования
  • ❌ API ключи
  • ❌ Токены доступа

Всегда:

  • ✅ Используйте blacklist для чувствительных полей
  • ✅ Устанавливайте подходящий TTL
  • ✅ Очищайте черновики после отправки
  • ✅ Проверяйте метаданные черновика

Резюме

Делайте:

  • ✅ Устанавливайте подходящий TTL
  • ✅ Очищайте черновики после отправки
  • ✅ Используйте blacklist для чувствительных полей
  • ✅ Используйте debounce для оптимизации
  • ✅ Обрабатывайте ошибки изящно

Не делайте:

  • ❌ Сохраняйте большие файлы
  • ❌ Игнорируйте TTL
  • ❌ Забывайте очищать черновики
  • ❌ Сохраняйте чувствительные данные
  • ❌ Устанавливайте слишком маленький debounce

Следующие шаги