react native with firebase validation input field - firebase

I want to validate my login form in react native. but i used another Firebase logging function in onChangetext in react native.
This is my onPress function in the login button press.
async onLoginPress() {
this.setState({ errorMessage: null, loading: true });
const { email, password } = this.state;
console.log(email);
console.log(password);
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then(() => {
this.setState({ loading: false });
// this.props.navigation.navigate("Friendlist");
})
.catch(() => {
//var errorCode = error.code;
//var errorMessage = error.message;
this.setState({
error: 'AUTHENTICATION FAILED',
loading: false
});
});
await AsyncStorage.setItem("email", email);
await AsyncStorage.setItem("password", password);
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.setState({
loading: false
});
}
});
}
and this is my onChangetext define in TextInput
onChangeText={email => this.setState({ email })}
I want to add validate functions with these functions. how caI i do that?

You can add multiple functions in the onChangeText callback as
onChangeText={async email => {
await method1()
await method2()
...
}}
but I would recommend you to use callback since you're using setState. This ensures the setState is updated before the callback in it is called
onChangeText={email => this.setState({ email }, () => this.validate(email))}

Related

Get value from firebase and use it in useState React native

First the user chooses his allergies by clicking on a toggle button. If the state is true or false the state is being added successfully to firebase.
Allergy Selctor Page
Then in my homepage I want to retrieve that allergy state and apply it in the allergy list state located on home page.
Home Page Image
I am able to get the state value from firebase using this
useEffect(() => {
firebase
.firestore()
.collection("userDb")
.where("userId", "==", user.email)
.onSnapshot(
(querySnapshot) => {
const newTypes = [];
querySnapshot.forEach((doc) => {
const type = doc.data();
newTypes.push(type);
});
setTypes(newTypes[0].Dairy);
setStatus(type);
},
(error) => {
console.log(error);
}
);
}, []);
useEffect(() => {
const fetchFav = async () => {
try {
const list = [];
await firebase
.firestore()
.collection("userDb")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const { Dairy, Peanut } = doc.data();
list.push({
userid: doc.id,
dairy: Dairy,
peanut: Peanut,
});
});
});
setPosts(list);
if (loading) {
setLoading(false);
}
} catch (e) {
console.log(e);
}
};
fetchFav();
searchApi(term);
}, []);
But I don't know how to apply this to my state. I wanted to use type in status(type) which gets the actual true/false value when I console log it gets the right value from firebase but for some reason its always true in status(type);
const [status, setStatus] = useState(type);
<Button
onPress={() => setStatus(!status)}
title={`Prevent Dairy: ${
status ? "on (search again for new results)" : "off"
}`}
></Button>
I want it to be dynamic as the user can change his allergies so I didn't use route.params for the allergies.
Any ideas appreciated. Thanks.

Why is firebase throwing a permission error after sign-out?

In a react-native application, dispatching an action that invokes firebase-auth to sign-out ends in a firebase permission error:
Here's the method inside the drawer component that dispatches the action:
logout = () => {
this.props
.logoutUser()
.then(() => {
this.props.navigation.navigate('Login');
})
.catch((err) => alert(err));
};
and here's the logout action:
export const logoutUser = () => {
return (dispatch) => {
return new Promise((resolve, reject) => {
firebase
.auth()
.signOut()
.then(() => {
dispatch({ type: types.RESET_APP });
console.log('Dispatching types.RESET_APP');
resolve();
})
.catch((error) => reject(error.message));
});
};
};
When executed, the screen reverts back to the login screen as desired. Console logs Dispatching types.RESET_APP, and THEN the error above displays.
authStateChanged Listener in my login:
export const loginUser = (email, password) => {
return (dispatch) => {
dispatch({ type: types.LOGIN_USER });
// listen for change in auth state before signing in
return new Promise((resolve, reject) => {
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((userCredential) => {
console.log('User Credential: ' + JSON.stringify(userCredential));
const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('Logged in: ' + user.email);
loginUserSuccess(dispatch, user);
resolve(user);
} else {
console.log('Authentication state changed, user object is null...');
//resetAuth();
}
});
// No longer need to listen to auth state
unsubscribe();
})
.catch((error) => {
console.log('Error during Email sign-in: ' + error);
loginUserFail(dispatch, error.message);
});
});
};
};
auth state observer is unsubscribed in the login function, so whats causing this?

How can i return the login page after signing up new user using firebase and react native?

Iam building an App with a signup and login feature but can't get to the login page after signing up.
I have tried to use react navigation as below
handleSignUp = () => {
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(function() {
// Sign-out successful.
this.props.navigation.navigate("logn")
})
// .then(signout=>{
// })
.catch(error => this.setState({ errorMessage: error.message }));
};
This leads me to the home page.
Register screen movement below member registration section.
handleSignUp = async () => {
const result = await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode == 'auth/weak-password') {
this.setState({ errorMessage: 'The password is too weak.' })
} else {
this.setState({ errorMessage: errorMessage })
}
});
if (result) {
this.props.navigation.navigate("logn")
}
}

Why are my redux actions not firing correctly?

I am trying to implement a check for authentication and to login/logout users using redux and firebase. I have the following code:
Action Types:
export const LOGIN_REQ = 'AUTH_REQ';
export const LOGOUT_REQ = 'LOGOUT_REQ';
export const AUTH_SUCCESS = 'AUTH_SUCCESS';
export const AUTH_FAILED = 'AUTH_FAILED';
export const GET_AUTH = 'GET_AUTH';
Reducers:
import * as ActionTypes from './ActionTypes';
export const auth = (state = {
isAuth: false,
user: null
}, action) => {
switch (action.type) {
case ActionTypes.LOGIN_REQ:
return { ...state, isAuth: false, user: null };
case ActionTypes.LOGOUT_REQ:
return { ...state, isAuth: false, user: null };
case ActionTypes.AUTH_FAILED:
return { ...state, isAuth: false, user: null };
case ActionTypes.AUTH_SUCCESS:
return { ...state, isAuth: true, user: action.payload };
case ActionTypes.GET_AUTH:
return state;
default:
return state;
}
}
Thunks:
export const getAuth = () => (dispatch) => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('Get AUTH called');
dispatch(authSuccess());
}
else {
console.log('Get AUTH called');
dispatch(authFailed());
}
});
}
export const loginReq = (email, password, remember) => (dispatch) => {
firebase.auth().signInWithEmailAndPassword(email, password)
.then((cred) => {
if (remember === false) {
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);
console.log('Logged In with Redux without persist');
}
else {
console.log('Logging in with Persist');
}
console.log('Dispatching Success !');
dispatch(authSuccess(cred.user.uid));
})
.catch((err) => {
console.log(err);
dispatch(authFailed(err));
});
}
export const logoutReq = () => (dispatch) => {
firebase.auth().signOut()
.then(() => dispatch(getAuth()))
.catch((err) => console.log(err));
}
export const authSuccess = (uid = null) => ({
type: ActionTypes.AUTH_SUCCESS,
payload: uid
});
export const authFailed = (resp) => ({
type: ActionTypes.AUTH_FAILED,
payload: resp
});
And I am calling it from a component as shown below:
const mapStateToProps = state => {
return {
isAuth: state.isAuth,
user: state.user
}
}
const mapDispatchToProps = dispatch => ({
getAuth: () => { dispatch(getAuth()) },
loginReq: (email, password, remember) => { dispatch(loginReq(email, password, remember)) },
logoutReq: () => { dispatch(logoutReq()) }
})
handleLogin() {
this.props.loginReq(this.state.email, this.state.password, this.state.remember);
}
handleLogOut() {
this.props.logoutReq();
}
<BUTTON onClick=()=>this.handleLogOut()/handleLogin()>
I am close to tears because I cannot figure out why my loginReq fires one or many gitAuth() methods even when i click on the button once. This happens only for the loginReq() action. I have not specified anywhere that loginReq() should fire it.
Also i have called the getAuth() method in the component did mount method of my main screen which checks authentication status once at the start of the app.
EDIT: I have console logged in the component did mount method in the main component so I know that this getAuth() call is not coming from there.
Imo the answer is badly done, try to reestructure it better, what you call "Thunks" are actually "Actions". But if I were to tell you something that could help is that maybe the problem lies in the thunk middleware config or with the way firebase is beign treated by the dispatcher, so I would say that you better try coding an apporach with the react-redux-firebase library (this one: http://react-redux-firebase.com/docs/getting_started ) it makes easier to connect redux with a firebase back end. Other great reference, the one that I learned with, is The Net Ninja's tutorial playlist about react, redux and firebase.
A friend of mine told me this has to do with something known as an 'Observer' which is in the onAuthStateChange() provided by firebase. Basically there is a conflict between me manually considering the user as authenticated and the observer doing so.

Calling a function inside .then() is throwing an error

I'm trying to perform some task with firebase and calling some functions inside promise without any callback function and this is giving me an error.
Here is my code
onButtonPress = () => {
const {email, password} = this.state
this.setState({error: '', loading: true});
firebase.auth().signInWithEmailAndPassword(email, password)
.then(this.onAuthSuccess().bind(this))
.catch(()=>{
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(this.onAuthSuccess().bind(this))
.catch(this.onAuthFailed().bind(this))
})
}
onAuthSuccess() {
this.setState({
email: '',
password: '',
error: '',
loading: false
})
}
onAuthFailed() {
this.setState({
error: "Authentication Failed",
loading: false
})
}
Here is the error message that I'm getting
undefined is not an object (evaluating '_this.onAuthSuccess().bind()')
3 ways of dealing with this context in ES6.
Use the bind keyword
onAuthSuccess() {
...
}
firebase.auth()
.then(this.onAuthSuccess.bind(this));
.catch(this.onAuthFailed.bind(this));
}
Use arrow function to avoid prebinding
onAuthSuccess = () => {
...
}
firebase.auth()
.then(this.onAuthSuccess);
.catch(this.onAuthFailed);
}
Bind your methods in the constructor
constructor(props) {
super(props);
this.onAuthSuccess = this.onAuthSuccess.bind(this);
}
Not 100% as the good ol this context is confusing!
so I think you want to get rid of the bind() and instead use => on your functions. Using the fat arrows will reset the context of this so this.setState should be right in the context of your class based component.
Here is an example of what I mean
onAuthSuccess = () => {
this.setState({
email: "",
password: "",
error: "",
loading: false
});
};
onAuthFailed = () => {
this.setState({
error: "Authentication Failed",
loading: false
});
};
onButtonPress = () => {
const { email, password } = this.state;
this.setState({ error: "", loading: true });
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(() => this.onAuthSuccess())
.catch(() => {
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(() => this.onAuthSuccess())
.catch(() => this.onAuthFailed());
});
};

Resources