如何在使用 redux 登录 facebook/expo 和 firebase 后显示用户数据

Posted

技术标签:

【中文标题】如何在使用 redux 登录 facebook/expo 和 firebase 后显示用户数据【英文标题】:How to show the User Data after logging in with facebook/expo and firebase using redux 【发布时间】:2017-12-12 02:41:25 【问题描述】:

目标: 1. 我想将我的用户的 public_profile 数据保存到 firebase 数据库 2. 我想在我的编辑配置文件屏幕组件之一中显示我的用户的 public_profile,并且能够对其进行编辑。

当前进展: 1. 我现在可以通过 facebook(expo) 对我的用户进行身份验证,并通过 Redux 在 firebase 身份验证控制台上显示它。

这是我的代码: 这是我的 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 );
  

;

这是我的 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);

请有人指导我,或者只是提供一个使用这种方法的教程或示例的链接。谢谢。

【问题讨论】:

【参考方案1】:

这是我的方法

在我的根容器中,我从数据库设置事件侦听器。当用户登录/登录时,我会触发一个登录请求,该请求会获取该用户的快照并将其作为用户存储到 redux 存储中。然后你可以将任何你想要的组件连接到商店...

链接到 repo 以供进一步参考。 https://github.com/GavinThomas1192/motoMechanicMeeKanic/blob/master/App/Containers/RootContainer.js 根容器...

  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 操作

 // ******** 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);
    );

;

【讨论】:

以上是关于如何在使用 redux 登录 facebook/expo 和 firebase 后显示用户数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用 redux 登录 facebook/expo 和 firebase 后显示用户数据

如何在页面打开后从 cookie 中正确设置属性(如果用户已登录)或使用路由器和 redux 在 React 中使用 F5

如何使用 MongoDB + NodeJS Express 向 ReactJS React Router 和 Redux 添加登录身份验证和会话?

如何使用passport-facebook身份验证重定向到用户登录react-redux应用程序的页面?

Redux,Fetch,如何捕获 json()

将 redux 操作添加到登录表单?