Search code examples
javascriptreactjsfirebasereact-nativereact-native-firebase

React Native Firestore infinite loop


I am trying to get user data from firestore using a documentSnapshot, i can get the data but it is stuck in an infinite loop, updating the user data,

here's the code

import firestore from '@react-native-firebase/firestore';
export default function HomeScreen() {
     const { user, logout } = useContext(AuthContext);
     const [currentUser, setCurrentUser] = useState('');

     useEffect(() => {
      firestore()
           .collection('users')
           .doc(user.uid)
           .get()
           .then(documentSnapshot => {
                if (documentSnapshot.exists) {
                     setCurrentUser(documentSnapshot.data())
                }
           })

 })
 return (
      <View style={styles.container}>
           <Title>{currentUser.displayName}</Title>
           <FormButton
                modeValue='contained'
                title='Logout'
                onPress={() => logout()} />
      </View>
 )
}

Solution

  • Every time you call setCurrentUser you're forcing a rerender (because this is a state variable). Your useEffect then fires again, which calls setCurrentUser again, and so on, causing the infinite loop.

    To prevent this, you should set a list of variables that useEffect should listen for before firing. You can do this by passing a second parameter to useEffect.

    useEffect(() => {
      // your function call
    }, [/* list of state/prop variables to respond to */])
    

    If you want useEffect to fire only once, similar to componentDidMount, you may pass an empty array.

    From the docs:

    If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.

    In your case it seems you may want to place user in this array, since that is the only variable your firestore call relies on. If user.uid has not changed, there is no reason to fire this effect again.