lwisi
lwisi

Reputation: 303

Component unable to fetch data from Firebase when navigating to it for the first time or coming back

Background

I'm building an app which displays a number of stores in the home screen. They are shown in a carousel which is filled up with information from a Firestore Collection and Firebase Storage. The user can navigate into each store by pressing on them. The Home Screen display works just fine every single time, but when navigating to one store components come back as undefined. This is the way I'm fetching the data:

export default function StoreDetailMain ({route}) { 

  const { storeId } = route.params
  const [store, setStore] = useState()
  useEffect(() => {

    const fetchQuery = async () => {
      const storeData = await firebase.firestore()
      .collection('stores/')
      .doc(storeId)
      .get()
      .then(documentSnapshot => {
        console.log('Store exists: ', documentSnapshot.exists);
        if (documentSnapshot.exists) {
          console.log('Store data: ', documentSnapshot.data());
          setStore(documentSnapshot.data())
          console.log(documentSnapshot.data())
        }
      });
    }

    fetchQuery()

  }, [storeId])

Then I'm rendering the information within tags as in <Text>{store.value}</Text>.

Problem

Navigating once to the store will always return a Component Exception: undefined is not an object (evaluating 'store.value'). However if I cut the "{store.value}" tags it works just fine. Then I can manually type them in again and they render perfectly. Once I go back to the Home Screen and try to go into another store I have to do it all again. Delete the calls for information within the return(), save the code, reload the app and type them in again.

What I have tried

Sometimes, not always, Expo will give me a warning about not being able to perform a React state update on an unmounted component. I thought this might be the problem so I gave it a go by altering my useEffect method:

export default function StoreDetailMain ({route}) { 

  const { storeId } = route.params
  const [store, setStore] = useState()
  useEffect(() => {
    let mounted = true;

    if(mounted){
    const fetchQuery = async () => {
      const storeData = await firebase.firestore()
      .collection('stores/')
      .doc(storeId)
      .get()
      .then(documentSnapshot => {
        console.log('Store exists: ', documentSnapshot.exists);
        if (documentSnapshot.exists) {
          console.log('Store data: ', documentSnapshot.data());
          setBar(documentSnapshot.data())
          console.log(documentSnapshot.data())
        }
      });
    }
    fetchQuery()
  }
    return () => mounted = false;

     }, [storeId])

This would not solve the issue nor provide any variation.

Question

Is this due to the unmounting/mounting of components? If so, wouldn't the useEffect method take care of it? If anyone could provide an explanation/solution it would be very much appreciated.

Thanks in advance.

Edit 1:

When the application fails to render the information, it doesn't print into the console the document snapshot. When it can render the data, it does log it. Thus the change in title.

Upvotes: 0

Views: 122

Answers (1)

Someone Special
Someone Special

Reputation: 13588

try giving it a initial value

const [ store, setStore ] = useState({value: ''})

or render it conditionally

{ store?.value && <Text>{store.value}</Text> }

secondly, route.params is defined? When you switching screens, did u make sure u pass the params? Switching from stack navigator to tab navigator for example, may drop the params.

Upvotes: 1

Related Questions