0

what's seems to be the problem in my code, i am createing a firestore & firebase based Application. Till now everything working fine but Now i want to add a unique key starting from 1 and then goes in ascending order to each of my item in firebase through which i can retrieve all the items in my FlatList Component. But i'm unable to do this. There is a problem which i currently facing, that when user fill the form and click the POST Button**[Details of the POST Button is Below]** the Data is Stored in the Firebase but the Counter Didn't incremented, After the Second Attempt (means user fill Another Form & Click on POST Button) the Value Finally Incremented.

Means After Two Form Fills the Counter Incremented By One but i want to increment the Counter on each of the Form Filled.

Please Help Me!

See The Code Below

const [adTitle, setAdTitle] = useState('')
const [adDescription, setAdDescription] = useState('')
const [yearOfPurchase, setYearOfPurchase] = useState('')
const [price, setPrice] = useState('')
const [contactNo, setContactNo] = useState('')
const [image, setImage] = useState('')
const [counter, setCounter] = useState(0)

i am using these stakes in my application all other working fine the problem comes to this one.

const [counter, setCounter] = useState(0)

and Call this function when ever user press post Button

const postData = async () => {
        if (!adTitle || !adDescription || !yearOfPurchase || !price || !contactNo) {
            Alert.alert("Please fill all the Fields")
            return
        }

        try {
            getCounter();                            // <-- called this function for Counter, Details are Below
            await fireStore().collection("ads").add({
                adTitle,
                adDescription,
                yearOfPurchase,
                price,
                contactNo,
                image,
                uniqueID: counter,
                uid: Auth().currentUser.uid
            })
            Alert.alert("Item Successfully Posted..")
            setAdTitle('')
            setAdDescription('')
            setYearOfPurchase('')
            setPrice('')
            setContactNo('')
            setImage('')
        } catch (err) {
            Alert.alert("Something went wrong\nPlease try again...")
        }

}

on call getCounter(); function it's fetch the current counter value from the firebase and then increment that value by one and then update the value in firebase

The Code of getCounter(); Function: (I think the Problem is right here in this getCounter(), But i'm unable to figure it out.)

const getCounter = async () => {
        try {
            const querySnap = await fireStore().collection('Counter').doc('count').get()
            setCounter((querySnap.data().counter)+1)
        } catch(error) {
            alert("Something went wrong\n[Error]: "+ error)
        }
        try {
            await fireStore().collection('Counter').doc("count").update({
                counter: counter
            })
        } catch {
            // alert("Something went wrong\nPlease try again...")
        }
    }

2 Answers2

1

I believe your problem lies on the fact that setCounter is run asynchronously and does not return a promise that you could use with async/await. In your case getCounter is called, triggers the setCounter function and then sends counter to firebase before setCounter has updated the value of counter.

The best solution I can imagine is using useEffect, as it can be used to monitor the value of counter and then trigger a function call when it is updated. So you could do the following:


const YourElement = () => {
   const getCounter = async () => {
        try {
            const querySnap = await fireStore().collection('Counter').doc('count').get()
            setCounter((querySnap.data().counter)+1)
        } catch(error) {
            alert("Something went wrong\n[Error]: "+ error)
        }
        try {
            await fireStore().collection('Counter').doc("count").update({
                counter: counter
            })
        } catch {
            // alert("Something went wrong\nPlease try again...")
        }
    }

   const postData = async () => {
        if (!adTitle || !adDescription || !yearOfPurchase || !price || !contactNo) {
            Alert.alert("Please fill all the Fields")
            return
        }

        try {
            getCounter()
            Alert.alert("Item Successfully Posted..")
            setAdTitle('')
            setAdDescription('')
            setYearOfPurchase('')
            setPrice('')
            setContactNo('')
            setImage('')
        } catch (err) {
            Alert.alert("Something went wrong\nPlease try again...")
        }

}

   useEffect(()=>{
      fireStore().collection("ads").add({
          adTitle,
          adDescription,
          yearOfPurchase,
          price,
          contactNo,
          image,
          uniqueID: counter,
          uid: Auth().currentUser.uid
          })},[counter])

   return <ChildElements/>
}

This way the data will only be sent to firebase after counter has been updated.

  • Thanks Brother, your logic not works for me, but it's helps me to figure out the actual problems. And Now the problem is Solved.... Thanks Once again – Muhammad Arsalan Apr 18 '21 at 19:26
1

I believe you are trying to access a variable that was not updated yet as you try to get the updated code on the same scope. An easy test you can do to see if that is the problem would be to change you code to something like this:

const getCounter = async () => {
        let newCounter = null

        try {
            const querySnap = await fireStore().collection('Counter').doc('count').get()
            newCounter = (querySnap.data().counter)+1
        } catch(error) {
            alert("Something went wrong\n[Error]: "+ error)
        }
        try {
            setCounter(newCounter)
            await fireStore().collection('Counter').doc("count").update({
                counter: newCounter
            })
        } catch {
            // alert("Something went wrong\nPlease try again...")
        }
    }

this way you guarantee the value you are passing to the firebase is calculated realtime before sending.