unsaveChangeWarning hooks
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
/**
|
||||
* هوک برای هشدار به کاربر هنگام خروج از صفحه با تغییرات ذخیره نشده
|
||||
* این هوک از رفرش، بستن تب، و navigation داخلی (دکمه برگشت، لینکها) جلوگیری میکند
|
||||
* @param isDirty - آیا فرم تغییر کرده است؟
|
||||
* @param message - پیام هشدار (اختیاری)
|
||||
*/
|
||||
export const useUnsavedChangesWarning = (
|
||||
isDirty: boolean,
|
||||
message: string = "تغییرات شما ذخیره نشدهاند. آیا مطمئن هستید که میخواهید این صفحه را ترک کنید؟"
|
||||
) => {
|
||||
const location = useLocation();
|
||||
const currentPath = useRef(location.pathname);
|
||||
const isNavigatingRef = useRef(false);
|
||||
|
||||
// برای جلوگیری از بستن/رفرش مرورگر
|
||||
useEffect(() => {
|
||||
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
if (isDirty) {
|
||||
e.preventDefault();
|
||||
e.returnValue = "";
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
if (isDirty) {
|
||||
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
};
|
||||
}, [isDirty]);
|
||||
|
||||
// برای جلوگیری از navigation داخلی (دکمه برگشت مرورگر)
|
||||
useEffect(() => {
|
||||
if (!isDirty) {
|
||||
currentPath.current = location.pathname;
|
||||
return;
|
||||
}
|
||||
|
||||
const handlePopState = () => {
|
||||
if (isDirty && !isNavigatingRef.current) {
|
||||
const confirmLeave = window.confirm(message);
|
||||
|
||||
if (!confirmLeave) {
|
||||
// اگر کاربر لغو کرد، به صفحه قبلی برگرد
|
||||
window.history.pushState(null, "", currentPath.current);
|
||||
} else {
|
||||
// اگر کاربر تایید کرد، اجازه navigation بده
|
||||
currentPath.current = location.pathname;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// یک state جدید به history اضافه کن تا بتونیم popstate رو catch کنیم
|
||||
window.history.pushState(null, "", location.pathname);
|
||||
|
||||
window.addEventListener("popstate", handlePopState);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("popstate", handlePopState);
|
||||
};
|
||||
}, [isDirty, message, location.pathname]);
|
||||
|
||||
// Update current path when location changes
|
||||
useEffect(() => {
|
||||
if (!isDirty) {
|
||||
currentPath.current = location.pathname;
|
||||
}
|
||||
}, [location.pathname, isDirty]);
|
||||
};
|
||||
Reference in New Issue
Block a user