Home > OS >  React native UseEffect and async issue
React native UseEffect and async issue

Time:12-24

im trying to get a StoreKey from firestore (v9), and put it inside another collection of DB as a path. for example, get storeKey (132, for example) and put inside collection(db, 'store', storeKey, 'coffeeDB') to access specific sub collection. I put two function (1: getData (storeKey), 2: access to sub collection) into UseEffect, so that it can run when it's mounted. However, I found UseEffect runs twice, initial storeKey shows Array [], and next run gets proper value which is 132. So, im having an error due to the first run. I guess it's because the second function inside UseEffect does not wait getData function to watch the data, but not too sure. How can I resolve this issue??

const getData = async(setStoreKey, setName) => {
console.log('xxxx')
const auth = getAuth();
const user = auth.currentUser;
if(user !== null){
    const email = user.email;
    
    const UserInfo = await getDoc(doc(db, 'users', email));
    if(UserInfo.exists()){
        setStoreKey(UserInfo.data().storeKey)
        setName(UserInfo.data().name);
    }
    else{
        console.log('None')
    }
    return
    
}
}

T

const StockScreen = ({ navigation }) => {
const [storeKey, setStoreKey] = useState([]);
const [userName, setName] = useState([]);
const [coffeeStock, setCoffeeStock] = useState([]);
useEffect(() => {
    
    getData(setStoreKey, setName);
    
    const unsub = onSnapshot(collection(db, 'Store', storeKey, 'coffeeDB'), (snapshot) => {
        setCoffeeStock(snapshot.docs.map((doc) =>  ({
            id: doc.id,
            data: doc.data(),
            number: doc.data(),
        })));
    });
    
    return unsub;
}, [storeKey]);

CodePudding user response:

Just remove dependency from second argument in useEffect and pass blank array

useEffect(() => {
    // your code
}, []);

It will run only once when your component is loaded. It is similar to componentDidMount of class component.

CodePudding user response:

The reason your useEffect run twice is because your storeKey state changing in getData(setStoreKey, setName) function. So what you can do here if you want to call getData() function once is to declare it on a separate useEffect function like:

useEffect(() => {
    getData(setStoreKey, setName); //call your getData function once
}, []);

And what I see is you need to update StoreKey every time for the unsub listener so with that above useEffect call another useEffect whenever the StoreKey dependency change like:

    useEffect(() => {
        getData(setStoreKey, setName); //call your getData function once
    }, []);

    useEffect(() => {        //another useEffect whenever storeKey changes
        const unsub = onSnapshot(collection(db, 'Store', storeKey, 'coffeeDB'), (snapshot) => {
            setCoffeeStock(snapshot.docs.map((doc) =>  ({
                id: doc.id,
                data: doc.data(),
                number: doc.data(),
            })));
        });
        
        return unsub;
    }, [storeKey]);

Hope this works for you.

  • Related