Mục lục

Đừng để User mất dữ liệu: Auto-Save Form

Hướng dẫn làm tính năng 'Lưu nháp' cho Form. Tự động lưu vào LocalStorage khi gõ phím. Khôi phục dữ liệu khi User quay lại.

Kịch bản ác mộng: User đang viết bài Blog dài 2000 chữ. Mất điện. Máy sập. Mở lại -> Form trắng tinh. -> User đập máy.

Là 1 Dev có tâm, hãy làm Auto-Save.

1. Cơ chế Auto-Save với LocalStorage

Ý tưởng:

  1. Lắng nghe mọi thay đổi của Form (watch).
  2. Lưu vào localStorage.
  3. Khi User vào lại trang -> Check localStorage -> Nếu có thì điền lại (reset).

2. Implementation

tsx:
import { useEffect } from "react";
import { useForm } from "react-hook-form";

const STORAGE_KEY = "draft_post_v1";

export function BlogForm() {
  const { register, watch, reset } = useForm();

  // 1. Load Draft khi mới vào
  useEffect(() => {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved) {
      const parsed = JSON.parse(saved);
      // Hỏi user trước khi restore (UX tốt)
      if (confirm("Tìm thấy bản nháp cũ. Bạn có muốn khôi phục không?")) {
        reset(parsed);
      }
    }
  }, [reset]);

  // 2. Lắng nghe thay đổi và Save
  useEffect(() => {
    const subscription = watch((value) => {
      // Lưu toàn bộ form value vào storage
      localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
    });
    
    return () => subscription.unsubscribe();
  }, [watch]);
  
  // 3. Xóa Draft khi Submit thành công
  const onSubmit = async (data) => {
    await saveToAPI(data);
    localStorage.removeItem(STORAGE_KEY); // Clean up
  };
  // ...
}

3. Tối ưu hóa (Debounce)

Việc ghi vào localStorage là đồng bộ (Sync) và khá chậm (chậm hơn RAM). Nếu form lớn mà ghi mỗi lần gõ phím -> Lag. Giải pháp: Debounce. Chỉ save sau khi user ngừng gõ 1 giây.

Sử dụng use-debounce hoặc lodash.debounce.

tsx:
// Custom Hook
function useAutoSave(data, key, delay = 1000) {
  const debouncedData = useDebounce(data, delay);

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(debouncedData));
  }, [debouncedData, key]);
}

Kết luận

Tính năng nhỏ nhưng "cứu mạng" User. Đặc biệt quan trọng với các form dài như: Viết bài, Đăng ký hồ sơ, Checkout. Hãy nhớ thêm logic Versioning cho key (vd: form_v2), đề phòng trường hợp bạn đổi cấu trúc form nhưng user vẫn load lại data cũ của form v1 -> Lỗi.

Quảng cáo
mdhorizontal