[React] 偵測用戶是否離開正在編輯畫面

MH Tsai
4 min readMay 9, 2021

用戶不小心要離開到編輯到一半的內容,如果可以跳個提示問是否要離開編輯,不失為一個貼心的好作法

這個的重要性不用我多說,直接進入重點。

用戶要離開會有兩種情況:
1. Url 變更或是關掉視窗
2. 關閉某個 component

設計概念

第一種情況比較單純,可以用 browser 預設的行為來解決(關鍵字:onbeforeunload),只要可以讓用戶觸發任何可輸入的元件時,指定 function 給 window.onbeforeunload 即可

第二種情況就需要自己實作一些功能:

1. 設一個 Boolean flag 決定目前是否是 dirty 狀態
2. 一個對應的 Modal 或是提示元件告知用戶正要離開是否放棄編輯

上 Code 👏

useUnsavedChange.tsx

import React, { useMemo, useState, useCallback } from 'react';import UnsavedChangeModal from '../components/modals/UnsavedChangeModal';
function useUnsavedChange() {
const [isDirty, setIsDirty] = useState(false);
const [showModal, setShowModal] = useState(false);
const [confirm, setConfirm] = useState<any>(() => () => undefined);
const checkUnsaved = useCallback(
({ confirm }) => {
if (isDirty) {
//show modal
setShowModal(true);
setConfirm(() => confirm);
return;
}
confirm();
},
[isDirty]
);
const CheckUnsavedModal = useMemo(() => {
return showModal ? (
<UnsavedChangeModal
onCancel={() => setShowModal(false)}
onConfirm={() => {
confirm();
setShowModal(false);
setIsDirty(false);
}}
/>
) : null;
}, [confirm, showModal]);
return {
setIsDirty: (isDirty) => {
if (isDirty) {
window.onbeforeunload = (e) => 'Discard Change?';
} else {
window.onbeforeunload = null;
}
setIsDirty(isDirty);
},
checkUnsaved,
isDirty,
CheckUnsavedModal,
};
}
export default useUnsavedChange;

這裡面實作了我上述提到的幾個重點:
1. 在用戶可以做操作的地方 (input, checkbox 之類的),可以透過 expose 出去的 setIsDirty 來達到同時設定 dirty flag 成 true 和指定 onbeforeunload,或是清除 dirty flag
2. 透過呼叫 checkUnsaved 可以觸發去檢查 dirty flag 是否為真,來決定要不要顯示客製的 Modal ,引導用戶繼續編輯或是離開

應用範例

Code Sandbox

歡迎有任何問題都可以直接透過社群媒體找我!
如果在工程師職涯或想轉職工程師上有任何想討論或是任何我可以幫忙,也歡迎在這裡進一步聯繫

找到更多我的資訊可以到這 mhtsai

如果這篇文章有幫到你的話,幫我拍個手吧!
對了,你知道每個人都可以拍50次手嗎?試試看吧!

感謝您的閱讀! :)

你還可以在這些地方找到我
Instagram, LinkedIn, Facebook, Github

--

--

MH Tsai

https://mhtsai.me | Software engineer by day, Web3 enthusiast by night. Dreams of being a productivity guru.