PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, June 29, 2022

[FIXED] How to show the User Data after logging in with facebook/expo and firebase using redux

 June 29, 2022     expo, facebook-sdk-4.0, react-native, redux     No comments   

Issue

GOAL:
1. I want to save the public_profile data of my user into firebase database
2. I want to show the public_profile of my user in one of my component which is edit profile screen, and be able to edit it.

CURRENT PROGRESS:
1. I'm now able to authenticate my user via facebook(expo) and show it on the firebase authentication console via Redux.

HERE IS MY CODE:
This is my auth_actions.js

import { AsyncStorage } from 'react-native';
import {
  FACEBOOK_LOGIN_SUCCESS,
  FACEBOOK_LOGIN_FAIL
} from './types';
import { Facebook } from 'expo';
import firebase from 'firebase';
// How to use Asyncstorage
// Asyncstorage.setItem('fb_token', token);
// AsyncStorage.getItem('fb_token');

export const facebookLogin = () => async dispatch => {
  let token = await AsyncStorage.getItem('fb_token');
  if (token) {
    //Dispatch an action saying FB login is done
    dispatch({ type: FACEBOOK_LOGIN_SUCCESS, payload: token });

  }else {
    // Start up F B Login process
    doFacebookLogin(dispatch);
  }
};

const doFacebookLogin = async dispatch => {
  let { type, token } = await Facebook.logInWithReadPermissionsAsync('215807715628181', {
    permissions: ['public_profile', 'email']
  });
  if (type === 'cancel'){
    return dispatch({ type: FACEBOOK_LOGIN_FAIL });
  }

  if (type === 'success'){
  await AsyncStorage.setItem('fb_token', token);
   const credential = firebase.auth.FacebookAuthProvider.credential(token);
  firebase.auth().signInWithCredential(credential).catch((error) => {
    console.log(error)
  });
  dispatch({ type: FACEBOOK_LOGIN_SUCCESS, payload: token });
  }

};

This is my LandingScreen.js

import React, { Component } from 'react';
import { View, Text, Image, StyleSheet, AsyncStorage } from 'react-native';
import { Button, SocialIcon } from 'react-native-elements';
import {Actions} from 'react-native-router-flux';
import { connect } from 'react-redux';
import * as actions from '../actions';

class LandingScreen extends Component {

  fbLoginPress() {
    this.props.facebookLogin();
    this.onAuthComplete(this.props);
    // Code for rebuilding the facebook authentication flow,
    // remove this when you want to try it on the first load.
    AsyncStorage.removeItem('fb_token');
  }

  componentWillReceiveProps(nextProps){
    this.onAuthComplete(nextProps);
  }

  onAuthComplete(props){
    if (props.token){
      Actions.home()
    }
  }

  render(){
    return (
      <View>
        <View>
          <Image
          resizeMode='contain'
          style={styles.landingImageStyle}
          source={require('../assets/risto-landing.png')}
          />
          <Text style={styles.titleAppStyle}>Risto </Text>
        </View>

        <View style={styles.buttonContainer}>
        <Button
        large
        title='Sign in With Facebook'
        backgroundColor='#4068AD'
        icon={{name: 'facebook-square', type: 'font-awesome'}}
        style={[styles.buttonStyle, styles.fbColor]}
        onPress={Actions.home}
        // onPress={this.fbLoginPress.bind(this)}
         />

         <Button
         large
         title='Sign In or Sign Up With Email'
         icon={{name: 'envelope', type: 'font-awesome'}}
         backgroundColor='#F8A443'
         style={[styles.buttonStyle, styles.emailColor]}
         onPress={Actions.emailLogin}
          />


        </View>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  landingImageStyle:{
    alignSelf: 'center',
    height: 350,
  },
  titleAppStyle:{
    alignSelf: 'center',
    textAlign: 'center',
    fontWeight: 'bold',
    fontSize: 18,
    marginTop: 40
  },
  buttonStyle:{
    marginTop: 20,
    borderRadius: 15,
    borderWidth: 4,
  },
  emailColor:{
    borderColor: '#F8A443'
  },
  fbColor:{
    borderColor: '#4068AD'
  },
  buttonContainer:{
    marginTop: 90
  }
});

function mapStateToProps({ auth }){
  return { token: auth.token };
}

export default connect (mapStateToProps, actions)(LandingScreen);

Please can someone guide me, or just give a link for a tutorial or an example which uses this kind of approach. Thank you.


Solution

Here is my approach

In my Root Container I setup event listeners from the DB. When a user signs/logs in I fire a login request that grabs a snapshot of this user and stores it to the redux store as user. Then you can connect whatever component you want to the store...

Link to repo for further reference. https://github.com/GavinThomas1192/motoMechanicMeeKanic/blob/master/App/Containers/RootContainer.js RootContainer...

  componentDidMount() {
// if redux persist is not active fire startup action
if (!ReduxPersist.active) {
  this.props.startup()
}

// ********* Add a listener from the database to monitor whos logged in. *********
firebase.auth().onAuthStateChanged((user) => {
  // ********* If a user is logged in firebase will return the user object. THEY ARE NOT LOGGED IN THOUGH *********
  if (user) {
    console.log('onAuthStateChanged', user)
    // ********* Then we call an official Firebase login function through actions *********
    this.props.loginRequest(user);
  } else {
    console.log('No user signed in')
  }
});

// ********* After logging in the found user from above we need to set them to redux store *********  
let signedInUser = firebase.auth().currentUser;

if (signedInUser) {
  this.props.loginRequest(signedInUser);
  console.log('currentUserSignedIn', signedInUser)
} else {
  console.log('no active user', signedInUser)
}

}

Redux Actions

 // ******** This is actually referencing the firebaseInitializeApp from the ./Containers/App ********
import firebase from 'firebase'


export const userSet = user => ({
    type: 'USER_SET',
    payload: user,
});

export const userCreate = user => ({
    type: 'USER_CREATE',
    payload: user,
});

export const userUpdate = user => ({
    type: 'USER_UPDATE',
    payload: user,
});

export const userSetRequest = user => dispatch => {
    return new Promise((resolve, reject) => {
        resolve(dispatch(userSet(user)));
    });
};



export const loginRequest = user => dispatch => {
    // ******** This gets called in RootContainer on mount, it will populate redux store with the entire User object from firebase ********
    // ******** FYI - The entire user object also contains their vehicles ********
    // ******** Here we need to check if user already exists in Firebase Database so that we dont overwrite their old data ********
    // ******** WARNING! With Firebase if you set data to a spot that has existing data it will overwrite it! ********
    console.log('RECIEVED USER TO LOOKUP', user);
    firebase.database().ref('users/' + user.uid).once('value').then(function (snapshot) {
        // ******** This method is straight from their docs ********
        // ******** It returns whatever is found at the path xxxxx/users/user.uid ********
        let username = snapshot.val();
        console.log(' FOUND THIS USER FROM THE DB', username);
        {
            // ******** If the username object is empty there wasn't any data at xxxxxx/user/user.uid ********
            // ******** It's safe to write data to this spot ********
            username === null ? firebase.database().ref('users/' + user.uid).set({
                account: username
            }).then(function () {
                console.log('STORED THIS USER TO FIREBASE DB', username);
                dispatch(userSet(username))
            })
                // ******** Otherwise, the user already exists and we should update redux store with logged in user ********
                : dispatch(userSet(username))
        }
    })
        .catch((err) => console.log(err));

    dispatch(userSet(user))
    console.log('INSIDE FIREBASEE DB SET', user)

};
export const signupRequest = (email, password, username) => dispatch => {
    // ******** The signup actions only trigger for first time users, no need to check database ********
    console.log('RECIEVED USER TO SIGNUP', email, password);
    firebase.auth().createUserWithEmailAndPassword(email, password)
        .then((authData) => {
            // ******** Firebase will create a route with whatever KEY is fed to the .set method ********
            // ******** We dont actually want this to avoid deep nesting ********
            // ******** So we package up our user.account object and .set(account) without any key value pairs ********
            let account = {}
            account.email = email.toLowerCase()
            account.uid = authData.uid
            account.username = username
            firebase.database().ref('users/' + authData.uid).set({
                account
            }).then(() => {
                // ******** Now we need to grap a snapshot from the DB to validate account creation and update the redux store locally ********
                firebase.database().ref('users/' + authData.uid).once('value').then(function (snapshot) {
                    let updatedUser = snapshot.val();
                    console.log(' FOUND THIS USER FROM THE DB after signup', username);
                }).then(() => {
                    dispatch(userSet(updatedUser));

                })
            })
        }).catch((err) => console.log(err));
};


export const passwordResetRequest = email => dispatch => {
    var auth = firebase.auth();

    let emailAccount = email.toLowerCase();
    console.log(emailAccount)
    auth.sendPasswordResetEmail(emailAccount).then(function () {
        console.log('Password reset email sent')
    }).catch(function (error) {
        console.log(error);
    });

};


Answered By - Gavin Thomas
Answer Checked By - David Goodson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing