What is the proper way to do that? My goal is to save in database the count of minutes of the video the user has watched until he closed the page and set the video's minutes to where he left off, next time he opens the very same video. I've tried to do that with beforeunload
event but the page is closing before the function return. I'm using async/await but I don't know how to make sure the event finish to run properly. I've tried something like this in my react component:
const ec = async (e) => await handleBeforeUnload(e);
window.addEventListener('beforeunload', ec);
return () => {
window.removeEventListener('beforeunload', ec);
}
but doesn't gurante that the function finish before leaving the page. What is the proper way to do that?
edit: here's the rest of the code:
const handleBeforeUnload = async (event) => {
await save_timestamp();
}
const save_timestamp = async () => {
const v:IResumeVideo = {
seconds: timeline.current,
video_id: video_id
}
const response = await fetch('/api/save_video', {
method: 'POST',
body: JSON.stringify(v)
});
const result = await response.json();
}
You can create a dedicated hook with sendBeacon
as Elvis mentioned in the comment, in this way you can use also for different cases in different components without duplicating same code
const useUnloadBeacon = ({ url, data }) => {
const handleUnload = async () => {
const jsonData = JSON.stringify(data);
const sendBeaconSuccess = navigator.sendBeacon(url, jsonData);
if(!sendBeaconSuccess) {
try {
const response = await fetch(url, {
method: 'POST',
body: jsonData,
headers: {
'Content-Type': 'application/json',
},
});
const result = await response.json();
} catch (error) {
console.error(error);
}
}
};
useEffect(() => {
window.addEventListener('unload', handleUnload);
return () => {
window.removeEventListener('unload', handleUnload);
};
}, [url, data]);
};
export default useUnloadBeacon;