Why can't I navigate to the screen "App" in the following code. I get the error:
Cannot read property 'navigate' of undefined
async signIn() {
const { username, password } = this.state
await Auth.signIn(username, password)
.then(user => {
this.setState({ user })
this.props.navigation.navigate("App");
Alert.alert('Signed In Successful!')
})
.catch(err => {
console.log('Error when signing in: ', err)
Alert.alert('Error when signing in: ', err)
})
}
}
You are mixing promises and await. You either await for the sign in, or remove the async/await and treat it like a promise. Also, it could be that you haven't binded the function so "this" points to undefined.
Either:
async signIn = () => {
const { username, password } = this.state
let user = await Auth.signIn(username, password);
this.setState({ user })
this.props.navigation.navigate("App");
Alert.alert('Signed In Successful!')
}
}
Or
signIn = () => {
const { username, password } = this.state
Auth.signIn(username, password)
.then(user => {
this.setState({ user })
this.props.navigation.navigate("App");
Alert.alert('Signed In Successful!')
})
.catch(err => {
console.log('Error when signing in: ', err)
Alert.alert('Error when signing in: ', err)
})
}
}
Related
When I run the function updatePassword I get the error "TypeError: user.getIdToken is not a function", which comes from a file in the firebase sdk.
async changePassword(state, payload) {
const user = auth.currentUser
let cred = EmailAuthProvider.credential(
payload.email,
payload.oldPassword
)
reauthenticateWithCredential(user, cred)
.then(() => {
// User re-authenticated.
console.log(payload.newPassword)
updatePassword(payload.email, payload.newPassword)
.then(() => {
// Update successful.
console.log('Succeed')
})
.catch((error) => {
console.log('Failed', error)
// An error ocurred
// ...
})
})
.catch((error) => {
// An error ocurred
// ...
console.log(error)
})
},
The updatePassword() function takes User as first parameter and not user's email. Try refactoring the code as shown below:
reauthenticateWithCredential(user, cred).then(({ user }) => {
// Pass user here and not payload.email
updatePassword(user, payload.newPassword).then(() => {
console.log('Succeed')
})
})
I am working on authentication for my react native app.
The problem I am having is that the signInUser function seems to be executing in the wrong order. I want the signIn function to fully execute before moving on.
However, that doesn't seem to be happening as I am getting this response in my console, with the "undefined" coming from console.log(response) in the SignInScreen.
Here is the console:
undefined
16d0707a3508a9b43b8c36c8574ca73d8b4b26af
I have this function in the SignInScreen.js
import { signIn } from "../services/authService";
import { useAuthDispatch } from "../contexts/authContext";
const SignInScreen = ({ navigation }) => {
const dispatch = useAuthDispatch();
const [signInLoading, setSignInLoading] = useState(false);
const signInUser = async (values) => {
const { email, password } = values;
setSignInLoading(true);
signIn(email, password)
.then((response) => {
console.log(response);
dispatch({
type: "SIGN_IN",
token: response,
});
})
.catch((e) => {
console.log(e);
})
.finally(() => setSignInLoading(false));
};
And this is my authService.js:
import axios from "axios";
const signIn = async (email, password) => {
axios
.post("http://127.0.0.1:8000/rest-auth/login/", {
username: email,
email: email,
password: password,
})
.then((response) => {
console.log(response.data.key);
return response.data.key;
})
.catch((error) => {
return error;
});
};
How can I fix this?
I am trying to implement the validation of password change and the issue I have is that I am not getting errorMessage back from the server in case of an error. I have managed to get it work and send back response after the password was updated. Also, I can console.log the error message on the back end but it's not returning an object with errorMessage to the front end.
if (!currentPassword) {
console.log("no current password");
return res
.status(400)
.json({ errorMessage: "Please confirm your current password" });
}
On the front code looks like this:
handleSubmit = (event) => {
event.preventDefault();
const authorization = localStorage.getItem("accessToken");
axios
.put(
`${process.env.REACT_APP_SERVER_URL}/settings/password`,
this.state.user,
{
headers: {
authorization,
},
}
)
.then((res) => {
if (res.errorMessage) {
console.log(res, "Unsuccessful password updated");
} else {
console.log("updating - res:", res);
this.setState({
user: res.data,
});
}
})
.catch((err) => {
console.log(err, "ERROR");
});
};
Everytime there is an error, I am not consol login the actual erroMessage but it is being catched in catch. What is the cause of that?
Thanks
Not a direct res its available under res.data.
Response schema of axios
use
if (res.data.errorMessage) {
instead of
if (res.errorMessage) {
For better understanding you need to console.log(res). Then you could understand the structure of the response
router.put("/password", isLoggedIn, (req, res, next) => {
const { currentPassword, newPassword, newPasswordConfirm } = req.body;
User.findById(req.user._id)
.then((user) => {
bcrypt.compare(currentPassword, user.password).then((isSamePassword) => {
if (!isSamePassword) {
console.log(
"Incorrect current password. To change your password try again!"
);
return res.status(400).json({
errorMessage:
"Incorrect current password. To change your password try again!",
});
}
return bcrypt
.genSalt(saltRounds)
.then((salt) => bcrypt.hash(newPassword, salt))
.then((hashedPassword) => {
User.findByIdAndUpdate(
req.user._id,
{ password: hashedPassword },
{ new: true }
)
.then((user) => {
console.log("user's password successfully changed");
res.status(200).json(user);
})
.catch((err) => {
res.status(500).json({ errorMessage: err.message });
});
})
.catch((err) => {
res.status(500).json({ errorMessage: err.message });
});
});
})
.catch((err) => {
console.log(err);
res.status(500).json({ errorMessage: err.message });
});
});
I have an action that currently works fine using .then but when I try and convert it to async ... await it suddenly can't access the first parameter of the function. The second parameter still works fine though.
Current function that works fine:
export const signInUser = (email, password) => {
return (dispatch) => {
return firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(() => {
console.log('signed in')
const { uid, email } = firebase.auth().currentUser
dispatch({ type: 'SIGN_IN', uid, email })
return dispatch(fetchAllData())
})
.catch(error => {
throw (error)
})
}
};
New function that doesn't work because 'email' is undefined.
export const signInUser = (email, password) => {
return async (dispatch) => {
console.log('testing')
console.log(password)
console.log('testing', email, password)
await firebase.auth().signInWithEmailAndPassword(email, password)
console.log('signed in')
const { uid, email } = firebase.auth().currentUser
dispatch({ type: 'SIGN_IN', uid, email })
return dispatch(fetchAllData())
}
};
The first console log of console.log('testing') works fine and outputs the string 'testing'. The second console log of console.log(password) also works fine and prints the inputted password. But the third console log console.log('testing', email, password) doesn't get shown at all.
This is how the function is called:
Parent component passes it to child component:
submit={(email, password) => dispatch(signInUser(email, password))}
Child component calls it:
const submitForm = (event) => {
event.preventDefault();
if (validForm) {
setLoading(true)
submit(email, password)
.catch(err => {
setLoading(false)
console.log('catch:', err.code)
setError(err.code)
})
}
}
The output I am receiving is catch: undefined.
Also, if I change the function to this:
export const signInUser = (email, password) => {
const userEmail = email
return async (dispatch) => {
console.log('testing')
console.log(password)
console.log('testing', userEmail, password)
await firebase.auth().signInWithEmailAndPassword(userEmail, password)
console.log('signed in')
const { uid, email } = firebase.auth().currentUser
dispatch({ type: 'SIGN_IN', uid, email })
return dispatch(fetchAllData())
}
};
Then it works fine. But I don't know why I would need to change it like this?
Thanks
Ok so the reason it wasn't working was because on the next line I was declaring email like this const { uid, email } = firebase.auth().currentUser
which was overriding the function parameter of email and therefore giving me the error that i was using email before it was declared.
I use email and password for login at first login and I have a token with getToken() function, after I add localStoreage with AsyncStoreage.setItem("ACCESS_TOKEN",token). I want to refresh to app signup with token and I use signInWithCustomToken(token) but I have an error. its 'auth/invalid-custom-token' (The token you provided is not valid.). I can't login.
DataStore.js
onLogin: function (Data) {
ApiRequest.login(Data)
.then((authData) => {
authData.getToken().then((token)=>{
AccessToken.set(token)
.then(() => Actions.login.completed(authData));
})
.catch((err) => Actions.login.failed(err))
})
.catch((err) => Actions.login.failed(err))
}
ApiRequest.Js
login(data) {
// first.login data = (email.password) && after.login data=(token)
return new Promise((next, error) => {
if (data && data.email && data.password) {
this.firebase.auth().signInWithEmailAndPassword(data.email,data.password)
.then((uData) => {;
next(uData)
})
.catch((err)=> error(err));
} else {
console.log("TOKEN:");
console.log(data);
this.firebase.auth().signInWithCustomToken(data)
.then((authData)=>next(authData))
.catch((err)=>{console.log("Error #232",err)})
}
});
}
AccessToken.Js
get(){
return new Promise((next,error) => {
if(this._accessToken) {
console.log("LastToken");
return next(this._accessToken);
}
AsyncStorage.getItem("ACCESS_TOKEN")
.then((token)=>{
if(token){
next(JSON.parse(token));
}else{
error()
}
})
.catch((err)=>error(err));
});
}
set(token){
this._accessToken=token;
return AsyncStorage.setItem("ACCESS_TOKEN",JSON.stringify(token));
}
Authenticate Listener
actions.auth.listen(function () {
AccessToken.get()
.then((token) => actions.login(token))
.catch((err) => actions.logout());
})
Token
eyJhb...Ckz95w