【问题标题】:React Native / Redux / Firebase - onAuthStateChanged not dispatchedReact Native / Redux / Firebase - onAuthStateChanged 未调度
【发布时间】:2018-05-30 18:58:00
【问题描述】:

我正在尝试使用 react native / redux / firebase 进行登录过程,但遇到了一些问题...

我尝试实现 onAuthStateChanged 来调度一个动作,但它没有按我的意愿工作。

它适用于两种情况:

1 - 我在我的组件中直接实现我的 onAuthStateChanged,如下所示:

componentDidMount() {
    firebaseAuth.onAuthStateChanged()
        .then((user) => {
            if (user) {
                Actions.home();
            } else {
                Actions.login();
            }
        });
}

2 - 我将它作为一个带有 redux-thunk 的动作实现但没有调度(但我无法调度一个动作并重定向到我的正确路线)

export const isAuthenticated = () => {
    firebaseAuth.onAuthStateChanged()
        .then((user) => {
            if (user) {
                console.log("launch.action#isAuthenticated - user already connected");
            } else {
                console.log("launch.action#isAuthenticated - user not connected");
            }
        });

};

而我想做的是这个(但不起作用):

export const isAuthenticated = () => {
return (dispatch) => {
    firebaseAuth.onAuthStateChanged()
        .then((user) => {
            console.log('user', user);
            if (user) {
                console.log("launch.action#isAuthenticated - user already connected");
                dispatch(isUserConnected(true));
            } else {
                console.log("launch.action#isAuthenticated - user not connected");
                dispatch(isUserNotConnected(true));
            }
        });
};

};

有人可以解释一下为什么它不适用于调度吗?

谢谢!

【问题讨论】:

  • 可以分享isUserNotConnectedisUserConnected的功能吗?

标签: firebase react-native react-redux redux-thunk


【解决方案1】:

。这是我的根容器中的一个示例,它几乎是我的最高组件

** 在您的情况下,您需要将 authStateChangeListener 移动到应用级别组件,例如在 componentDidMount() 中。然后将您的关注点分开,如果用户存在....然后从您的操作中调用一个函数来调度商店更新。

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

}

这是我的登录请求,它存在于我的操作中

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)

};

【讨论】:

  • 所以我想我的操作中不可能有 onAuthStateChangedListener ?有一个 litener 只适用于组件?
  • 简短的回答是肯定的,你可以把它们放在你的行动中。但是您仍然需要从您的应用级别调用它们。所以在第一个答案中,他就是这样做的。看看我为你更新的内容
  • 我刚刚将您的功能连接到我的应用程序中,它不适用于您的所有操作。
【解决方案2】:

两件事:

  1. 使用一个函数(例如,isUserConnected)并将值设置为 truefalse(而不是像您当前那样使用两个不同的函数,isUserNotConnectedisUserConnected )

  2. 根据firebase documentationfirebaseAuth 更改为firebase.auth()


试试这个。

(这对我有用)

在 Redux(操作)中:

// Firebase
import firebase from 'firebase';

// Redux Function
export const testFirebaseInRedux = () => {
  return (dispatch, getState) => {
    firebase.auth().onAuthStateChanged(function (user) {
      if (user) {
        console.log("testFirebaseInRedux: logged in");
        dispatch(isUserConnected(true));
      } else {
        console.log("testFirebaseInRedux: not logged in");
        dispatch(isUserConnected(false));
      }
    })
  }
}

export const isUserConnected = (payloadToSet) => {
  return {
    type: 'IS_USER_CONNECTED',
    payload: payloadToSet
  }
}

在 Redux(减速器)中:

export default function (state=initialState, action) {
  switch(action.type) {
  case 'IS_USER_CONNECTED':
    return {
      ...state,
      isUserConnected: action.payload
    }
  default:
    return {
        ...state
    }
  }
}

组件:

// Libraries
import React from 'react';

// Redux
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {testFirebaseInRedux} from './../actions/index.js';

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

  componentDidMount() {
    this.props.testFirebaseInRedux()
  }

}

function mapStateToProps(state) {
    return {
      user: state.user
    };
}

function matchDispatchToProps(dispatch) {
    return bindActionCreators({
      testFirebaseInRedux: testFirebaseInRedux,
    }, dispatch)
}


export default connect(mapStateToProps, matchDispatchToProps)(YourComponent);

【讨论】:

  • 我的 firebaseAuth 是 firebase.auth()。而我所拥有的,正是你所做的。事实上,当我使用返回(调度)的东西时,它永远不会进入 onAuthStateChanged 响应中......:/
猜你喜欢
  • 2018-05-16
  • 2020-08-26
  • 2018-04-19
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 2018-12-30
  • 2019-10-11
  • 2017-11-30
相关资源
最近更新 更多