Refresh page after and call a function automatically in react - reactjs

I want to create a function that refreshes the page and then call element and click:
const handlePDF = () => {
window.location.reload(false);
pdfRef.current.click()
};
I had thought about setTimeout but it doesn't work like that either.
I imagine that I have to save that order in memory once the page is refreshed but I don't know how to do it.
I appreciate your help guys.

You can use sessionStorage on window load event to solve that.
1. Listen window on load
window.onload = () => {
let reloading = sessionStorage.getItem("reloading");
if (reloading) {
sessionStorage.removeItem("reloading");
pdfRef.current.click();
}
}
2. Save a session on handlePDF call
const handlePDF = () => {
sessionStorage.setItem("reloading", "true");
window.location.reload(false);
};

I had a similar requirement to your's, before.
The solution that I settled with is to use sessionStorage to flag states, so that some flag is available to you, upon page refresh.
Then, you'd look for that flag in a useEffect callback.
But first, let's create a constant, so that we don't aimlessly repeat ourselves.
const handlePdfFlag = 'handle_pdf';
Then, create the flag in localStorage, then reload the page.
const handlePDF = () => {
sessionStorage.setItem(handlePdfFlag, 'true');
window.location.reload(false);
};
Then, in some useEffect, you'd pick up the flag, ensuring that you delete the flag afterwards.
useEffect(() => {
if (sessionStorage.getItem(handlePdfFlag) === 'true' && pdfRef.current) {
sessionStorage.removeItem(handlePdfFlag);
pdfRef.current.click();
}
});

If you want a function that does some code based on something changing then maybe the useEffect hook will work for you.

Related

Need to call a method when users closes tab

From few days I am facing a challenge. I want to call a method when user close a tab or window, so before closing the tab I want to execute a method. I am working in functional component ReactJS. It will be very helpful if get some solution regarding my query. I am placing my logout method inside that but it is getting triggered multiple times ?
window.addEventListener("beforeunload", (ev) =>
{
ev.preventDefault();
onLogOut();
return ev.returnValue = 'Are you sure you want to close?' ;
});
I need to implement the onLogOut
But the way I am using it the logout method is triggered multiple times. Any solution to make it call only once ?
If you're using React, please consider implementing such code in useEffect with a clean up function, for more information about clean up function in react
useEffect(() => {
window.addEventListener("beforeunload", (ev) => { ev.preventDefault(); __onLogOut(); return ev.returnValue = 'Are you sure you want to close?'; });
return() => {
window.removeEventListener('beforeunload')
}
},[])

Supabase onAuthStateChange() triggers when switching tabs in React

I have the following code in my React project using Supabase:
// supabaseClient.ts
export const onAuthStateChangedListener = (callback) => {
supabase.auth.onAuthStateChange(callback);
};
// inside user context
useEffect(() => {
const unsubscribe = onAuthStateChangedListener((event, session) => {
console.log(event);
});
return unsubscribe;
}, []);
However, every time I switch tabs away from the tab rendering the website to something else, and back, I see a new log from this listener, even if literally no change happened on the website.
Does anyone know the reason for this? The useEffect inside my user context component is the only place in my app where the listener is being called. To test, I wrote this dummy function inside my supabaseClient.ts file:
const testFunction = async () => {
supabase.auth.onAuthStateChange(() => {
console.log("auth state has changed");
});
};
testFunction()
This function also renders every time I switch tabs. This makes it a little annoying because my components that are related to userContext re render every time a tab is switched, so if a user is trying to update their profile data or something, they cannot switch tabs away in the middle of editing their data.
Supabase onAuthStateChange by default triggers every time a tab is switched. To prevent this, when initializing the client, add {multiTab: false} as a parameter.
Example:
const supabase = createClient(supabaseUrl, supabaseAnonKey, {multiTab: false,});
Here is my solution to the same problem. The way I've found is saving the access token value in a cookie every time the session changes, and retrieve it when onAuthStateChange get triggered, so I can decide to not update anything if the session access token is the same.
// >> Subscribe to auth state changes
useEffect(() => {
let subscription: Subscription
async function run() {
subscription = Supabase.auth.onAuthStateChange(async (event, newSession) => {
// get current token from manually saved cookie every time session changes
const currentAccessToken = await getCurrentAccessToken()
if (currentAccessToken != newSession?.access_token) {
console.log('<<< SUPABASE SESSION CHANGED >>>')
authStateChanged(event, newSession)
} else {
console.log('<<< SUPABASE SESSION NOT CHANGED >>>')
}
}).data.subscription
// ** Get the user's session on load
await me()
}
run()
return function cleanup() {
// will be called when the component unmounts
if (subscription) subscription.unsubscribe()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

ReactJS delay update in useState from axios response

I am new to react js and I am having a hard time figuring out how to prevent delay updating of use state from axios response
Here's my code:
First, I declared countUsername as useState
const [countUsername, setUsername] = useState(0);
Second, I created arrow function checking if the username is still available
const checkUser = () => {
RestaurantDataService.checkUsername(user.username)
.then(response => {
setUsername(response.data.length);
})
.catch(e => {
console.log(e);
})
}
So, every time I check the value of countUsername, it has delay like if I trigger the button and run checkUser(), the latest response.data.length won't save.
Scenario if I console.log() countUseranme
I entered username1(not available), the value of countUsername is still 0 because it has default value of 0 then when I trigger the function once again, then that will just be the time that the value will be replaced.
const saveUser = () => {
checkUser();
console.log(countUsername);
}
Is there anything that I have forgot to consider? Thank you
usually there is a delay for every api call, so for that you can consider an state like below:
const [loading,toggleLoading] = useState(false)
beside that you can change arrow function to be async like below:
const checking = async ()=>{
toggleLoading(true);
const res = await RestaurantDataService.checkUsername(user.username);
setUsername(response.data.length);
toggleLoading(false);
}
in the above function you can toggle loading state for spceifing checking state and disable button during that or shwoing spinner in it:
<button onClick={checking } disabled={loading}>Go
i hope this help
.then is not synchronous, it's more of a callback and will get called later when the api finishes. So your console log actually goes first most of the time before the state actually saves. That's not really something you control.
You can do an async / await and return the data if you need to use it right away before the state changes. And I believe the way state works is that it happens after the execution:
"State Updates May Be Asynchronous" so you can't really control when to use it because you can't make it wait.
In my experience you use the data right away from the service and update the state or create a useEffect, i.g., useEffect(() => {}, [user]), to update the page with state.
const checkUser = async () => {
try {
return await RestaurantDataService.checkUsername(user.username);
} catch(e) {
console.log(e);
}
}
const saveUser = async () => {
const user = await checkUser();
// do whatever you want with user
console.log(user);
}

React Render UI Before Redirect

I am having problem rendering ui before redirect in react. I has a variable is called from api, i want to check if it is 'x' then will redirect. But ui will render before redirect.
Bellow is my code:
useLayoutEffect(() => {
getProfile().then((res) => {
setIsLoading(true);
if (res) {
redirectByUserType(res.data.type); // redirect to /home
}
});
}, []);
I tried using useLayoutEffect but not working.
Please help me, thank you so much.
If you don't want to render until getProfile() has finished, then have a state variable which tracks whether it is finished. If it hasn't finished, return null to render nothing. If it has, return whatever you want to render. I would normally call this state variable loading, but you seem to already have one with that name, who's purpose i don't know. Maybe you can piggy back on that, maybe you need a separate one:
const [ready, setReady] = useState(false);
useEffect(() => {
getProfile().then(res => {
setIsLoading(true);
if(res) {
redirectByUserType(res.data.type);
} else {
setReady(true)
}
});
}, []);
if (!ready) {
return null;
}
return (
<div>Something</div>
);

Best way to detect if a user leaves the page in React (i.e. refresh, close tab, or change url) [duplicate]

I want a function, to send a request to a server (don't care about response) before a user refreshes the page.
I've tried using the componentWillUnmount approach but the page refresh doesn't call this function. e.g.
import React, { useEffect } from 'react';
const ComponentExample => () => {
useEffect(() => {
return () => {
// componentWillUnmount in functional component.
// Anything in here is fired on component unmount.
// Call my server to do some work
}
}, []) }
Does anyone have any ideas how to do this?
You could try listening for the window.beforeunload event.
The beforeunload event is fired when the window, the document and its
resources are about to be unloaded. The document is still visible and
the event is still cancelable at this point.
useEffect(() => {
const unloadCallback = (event) => { ... };
window.addEventListener("beforeunload", unloadCallback);
return () => window.removeEventListener("beforeunload", unloadCallback);
}, []);
Note: This will respond to anything that causes the page to unload though.
Note 2:
However note that not all browsers support this method, and some
instead require the event handler to implement one of two legacy
methods:
assigning a string to the event's returnValue property
returning a string from the event handler.
You can do this, almost, by checking if the page has been refreshed.
Source: https://developer.mozilla.org/en-US/docs/Web/API/Navigation_timing_API
Example:
if (window.performance) {
console.info("window.performance is supported");
console.info(performance.navigation.type);
if (performance.navigation.type == performance.navigation.TYPE_RELOAD) {
console.info( "This page is reloaded" );
} else {
console.info( "This page is not reloaded");
}
}

Resources