Home > front end >  How can I execute conditionally when using useEffect in Reactnative?
How can I execute conditionally when using useEffect in Reactnative?

Time:08-21

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);
}
  • Related