I created an async function called func in useEffect. When data is received from firestore, "urlsdata" data is saved with setUrl. After that, if there is data in the url contained in useState, I hide the SplashScreen and change the renderbool to true. However, when useEffect is executed when the app is first rendered, for some reason it is executed twice, so the api is executed twice in total. I think this is very unnecessary, so the code below is executed only when renderbool is false.
But it still gets executed twice when renderbool is false. How do I make func run only once?
Note that url and renderbool are mandatory.
this is my code
const [url, setUrl] = useState('');
const [renderbool, setRenderbool] = useState(false);
useEffect(() => {
const func = async () => {
if(!renderbool) {
const urlsdata= await storage().ref('/main.jpg').getDownloadURL();
setUrl(urlsdata);
if(url) {
SplashScreen.hide();
setRenderbool(true);
}
}
}
func();
},[url, renderbool]);
CodePudding user response:
Your useEffect
is dependent on two variables i.e. url
and renderbool
in addition to executing on first render, it will execute when ever these variables are re-assigned. Meaning you are listening for changes of url
and changing it on the same method.
If you only need to fetch the url once then create a useEffect
with []
, get the url in this one and have and have another useEffect
with [url]
which hides the splash screen.
If you don't like this idea then simply create a flag that indicates whether, it has executed, like const [splashHidden, setSplashHidden] = useState(false);
then check for this
//EVIL EVIL
if(splashhidden)
{
setSplashHidden(true);
//rest of the code
}
this should force it to only execute once... however the first option is the better way
CodePudding user response:
I think you need to change your second if statement.
When you set a state, you can't immediately check the value of it. The state will be updated after your code done running. So, in your case, the first time your useEffect
run (on mount) and when you check
setUrl(urlsdata); <- url state still empty here
if (url) <- this will return false, which leaves your `renderbool` state still `false`.
But, because your url
state is now changed after the code is done, the useEffect
will be called again for the second time. So, what you can do is to check your urlsdata
instead
if (urlsdata) {
SplashScreen.hide();
setRenderbool(true);
}