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>
)
}
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.