Matt Laszcz
Matt Laszcz

Reputation: 409

Sending and Retrieving user ID from Firebase Firestore

I am using Firebase.auth() to authenticate a login with Google Firebase then I retrieve the UID and send it to my Redux Store. The UID is not being sent to the store unless I navigate to the next page then return to the login page. It seems my order of operations is off, how can I get the UID in my Redux store without haveing to re-login/ refresh the page.

class Home extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            id: ''
        }
    }

id (value) {
        this.props.id(value);
    }
handleLogin = (load) => {

        const { email, password } = this.state

        Firebase.auth()
            .signInWithEmailAndPassword(email, password)
            .then(async cred => {
                return db.collection('users').doc(cred.user.uid).set({
                    test: 'test'
                })
            })
            .then(() => this.props.navigation.navigate('AddProfiles'))

            .catch(error => console.log(error))
        

        const currentUser = firebase.auth().currentUser;
        
        const userId = currentUser["uid"];
       
        this.setState({
            id: userId
        })
        this.props.id(this.state.id);
    }

<TouchableOpacity style={styles.signupbutton}>
      <Button
           color='white'
           title="Log in"
           onPress={(payload) => this.handleLogin()}
       />
</TouchableOpacity>
const mapStateToProps = (state) => {
    return {
        counter: state.counter,
        value: state.id
    };
}

const mapDispatchToProps = dispatch => {
    return {
        id: (value) => dispatch({ type: 'id', payload: value })
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(Home)

Upvotes: 0

Views: 797

Answers (1)

jnpdx
jnpdx

Reputation: 52397

Right now, the code starting with the line const currentUser is running before the signInWithEmailAndPassword completes, since signInWithEmailAndPassword is an asynchronous function. The reason that it works on refresh is at that point, firebase.auth().currentUser has a value, so

You can move your code inside the then block so that it runs only when the function is complete. It'll look something like this (untested, because I don't have the rest of your code):

handleLogin = (load) => {

        const { email, password } = this.state

        Firebase.auth()
            .signInWithEmailAndPassword(email, password)
            .then(async cred => {
                this.setState({
                 id: cred.user.uid
                })
                this.props.id(cred.user.id);
                return db.collection('users').doc(cred.user.uid).set({
                    test: 'test'
                })
            })
            .then(() => this.props.navigation.navigate('AddProfiles'))

            .catch(error => console.log(error))
}

Note that setState is also asynchronous, so calling this.props.id(this.state.id); right after setState is likely to fail on the first run.

Although the above should fix the immediate issue, I'd suggest onAuthStateChanged: https://firebase.google.com/docs/auth/web/start#set_an_authentication_state_observer_and_get_user_data

This way, you can do your sign in and set the Redux state based on its value or run the same code to set the Redux value when the user just returns to a page. It'll probably lead to a more robust situation than tying everything to signInWithEmailAndPassword

Upvotes: 1

Related Questions