I'm trying to make a login process with react native / redux / firebase and i got some issues...
I try to implement onAuthStateChanged to dispatch an action, but it's not working as i want.
It's working for two cases :
1 - I implement directly my onAuthStateChanged in my component like below :
componentDidMount() {
firebaseAuth.onAuthStateChanged()
.then((user) => {
if (user) {
Actions.home();
} else {
Actions.login();
}
});
}
2 - I implement it in as an action with redux-thunk but without dispatch (but then i cant dispatch an action and redirect to my correct route)
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");
}
});
};
And what i want to do is this (but doesn't work) :
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));
}
});
};
};
Can someone explain me why it doesn't work with the dispatch ?
Thanks!
Two things:
Use one function (for example, isUserConnected
) and setting the value to either true
or false
(instead of using two different functions, isUserNotConnected
and isUserConnected
, as you currently are)
Change firebaseAuth
to firebase.auth()
per the firebase documentation
Try this.
(This works for me)
In Redux (actions):
// 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
}
}
In Redux (reducers):
export default function (state=initialState, action) {
switch(action.type) {
case 'IS_USER_CONNECTED':
return {
...state,
isUserConnected: action.payload
}
default:
return {
...state
}
}
}
Component:
// 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);
. Here is an example from my Root Container, which is almost my highest component
** In your case You need to move your authStateChangeListener to an app level component, like inside a componentDidMount(). Then separate your concerns, if user exists.... THEN call an function from your actions that DISPATCHES a store update.
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)
}
}
And this is my loginRequest that lives within my actions
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)
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.