I have made a user login function:
export const userLogin = (email, password) => (dispatch) => {
console.log(email, password);
dispatch({ type: actionTypes.AUTH_LOGIN_STARTED });
console.log("after dispatch");
Parse.User.logIn(email, password, {
success(user) {
console.log("in success");
dispatch({
type: actionTypes.AUTH_LOGIN_SUCCESS,
user: user.toJSON(),
});
window.location.replace('/');
},
error(user, error) {
console.log("in error")
console.log({ error });
// The login failed. Check error to see why.
dispatch({
type: actionTypes.AUTH_LOGIN_ERROR,
error,
});
},
});
};
but it always gets stuck after Parse.User.logIn it doesn't go in a success or in error. I have logged the email and password and they are correct.
So what am I missing here?
Parse.User.Login does not have any third parameter. You should be using the promise functions:
Parse.User.logIn(email, password)
.then((user) => {
console.log("in success");
dispatch({
type: actionTypes.AUTH_LOGIN_SUCCESS,
user: user.toJSON(),
});
window.location.replace('/');
})
.error((user, error) => {
console.log("in error")
console.log({ error });
// The login failed. Check error to see why.
dispatch({
type: actionTypes.AUTH_LOGIN_ERROR,
error,
});
});
Or, if you're fancy enough, you can use the new await syntax (Which I think is a bit cleaner):
export const userLogin = (email, password) => async (dispatch) => {
console.log(email, password);
dispatch({ type: actionTypes.AUTH_LOGIN_STARTED });
console.log("after dispatch");
try {
const user = await Parse.User.logIn(email, password);
console.log("in success");
dispatch({
type: actionTypes.AUTH_LOGIN_SUCCESS,
user: user.toJSON(),
});
window.location.replace('/');
} catch (error) {
console.log("in error")
console.log({ error });
// The login failed. Check error to see why.
dispatch({
type: actionTypes.AUTH_LOGIN_ERROR,
error,
});
}
};
Related
iam using react-redux here and when i use trycatch block it not triggers error when error is executed.why??
import {
LOGIN_REQUEST,
LOGIN_SUCCESS,
LOGIN_FAIL,
CLEAR_ERRORS,
} from "../constants/userConstant";
impo
rt axios from "axios";
export const login = (email, password) => async (dispatch) => {
try {
dispatch({ type: LOGIN_REQUEST });
const config = { headers: { "Content-Type": "application/json" } };
const { data } = await axios.post(
`/api/v1/login`,
{ email, password },
config
);
dispatch({ type: LOGIN_SUCCESS, payload: data.user });
} catch (error) {
dispatch({ type: LOGIN_FAIL, payload: error.response.data.message });
}
};
//Clearing errors
export const clearErrors = () => async (dispatch) => {
dispatch({ type: CLEAR_ERRORS });
};
=>It was showing LOGIN_FAIL in react-redux-devtools but it was not throwing an error
catch (error) {
dispatch({ type: LOGIN_FAIL, payload: error.response.data.message });
// Log your error in the console
console.log(error);
// throw error
throw error
}
If you want to console error or throw error do it this way but you actually just call your dispatch for the moment.
The try catch blocks are here to handle every situations your function meet, when an error come it's been caught but YOU have to decide how to handle this error.
I try a lot of things but I can´t go on .. I stucked ...
If I login in to my account it works I get also my userInfo but only userID and my password.. but I would have my token also ..
I wrote an if state where I catch my token but I want to set it also in the localStorage and I don´t know how to do it..
export const login = (userID, password) => async (dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const url = "http://localhost:8080/authenticate/";
const config = {
auth: {
username: userID,
password,
},
};
const data = {};
const response = await axios.post(
url,
data,
config,
)
dispatch({ type: USER_LOGIN_SUCCESS, payload: config});
//localStorage.setItem("userInfo", JSON.stringify(config) );
if (response.status === 200) {
// Login succeeded
const token = response.data.token;
console.log("TOKEN\n" + token);
localStorage.setItem("userInfo", JSON.stringify(config) );
}
} catch (error) {
//alert("Sorry, login failed");
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.ErrorMessage
? error.response.data.ErrorMessage
: error.message,
});
}
};
try this
export const login = (userID, password) => async (dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const url = "http://localhost:8080/authenticate/";
const config = {
auth: {
username: userID,
password, //this should not be saved in your local storage delete this from here
},
};
const data = {};
const response = await axios.post(
url,
data,
config,
)
dispatch({ type: USER_LOGIN_SUCCESS, payload: config});
if (response.status === 200) {
// Login succeeded
config.token = response.data.token;
}
localStorage.setItem("userInfo", JSON.stringify(config) );
} catch (error) {
//alert("Sorry, login failed");
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.ErrorMessage
? error.response.data.ErrorMessage
: error.message,
});
}
};
Ok So i am trying to display my backend error messages in the front end, so I have it setup to send the response with the error code and a message and then in my action I am setting a state in my React component which I will then use to display the error message, so far I can get to display the error code but that is no use to most users so I would like to access the message I send with the code! So I want it to say user already exists or passwords do not match rather than Error: Request failed with status code 400
my action
export const signup = (form, router, setError) => async (dispatch) => {
const changeError = (error) => {
setError(error);
};
try {
const { data } = await api.signup(form);
dispatch({ type: AUTH, data });
router.push("/");
} catch (error) {
console.log(error);
changeError(error);
}
};
my node signup
export const signup = async (req, res) => {
const { email, password, confirmPassword, firstName, lastName } = req.body;
try {
const existingUser = await user.findOne({ email });
if (existingUser)
return res.status(400).json({ message: "User already exists." });
if (password != confirmPassword)
return res.status(400).json({ message: "Passwords do not match." });
const hashedPassword = await bcrypt.hash(password, 12);
const result = await user.create({
email,
password: hashedPassword,
name: `${firstName} ${lastName}`,
});
const token = jwt.sign(
{ email: result.email, id: result._id },
process.env.JWT_KEY,
{
expiresIn: "1h",
}
);
res.status(200).json({ result, token });
} catch (error) {
res.status(500).json({ message: "Something went wrong." });
}
};
After little search on Google, if you are using Axios as your api, the path to the error message is:
error.response.data.message
else, have you tried somthing like this?
error.data.message
or
error.message
as Guy said, slightly before I found the answer myself I set the error to error.response.data.message
so now I can set my error in the front end to display the message
and yea sorry was using axios, I'll know better for next time to mention that!
export const signup = (form, router, setError) => async (dispatch) => {
const changeError = (error) => {
setError(error);
};
try {
const { data } = await api.signup(form);
dispatch({ type: AUTH, data });
router.push("/");
} catch (error) {
console.log(error);
changeError(error.response.data.message);
}
};
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 want to sign in to in my react native app using firebase authentication. For example, to login with email and password i have the following function, which is basically a redux action:
export const userSignin = (email, password) =>
async dispatch => {
try {
dispatch({ type: 'auth_attempt_started' })
const user = await firebase.auth().signInWithEmailAndPassword(email.trim(), password)
saveUserDataToAsyncStorage(user)
if (!TASKS_SORT_BY && !TASKS_SORT_ORDER)
dispatch(getTasksSortData(user.user.uid))
if (!EMPLOYEES_SORT_BY && !EMPLOYEES_SORT_ORDER)
dispatch(getEmployeesSortData(user.user.uid))
if (!ACCOUNTS_SORT_BY && !ACCOUNTS_SORT_ORDER)
dispatch(getAccountsSortData(user.user.uid))
goToMain()
setTimeout(() => {
dispatch({
type: 'user_signedin',
payload: user
})
}, 100);
}
catch (err) {
dispatch({
type: 'auth_error',
payload: err.toString()
})
}
}
This function throw an error if something went wrong with the signin process.
The problem is when the internet connection is slow, the signin process take a long time before the success or the failure, sometimes around 30 seconds which is very bad for the user experience.
The question is:
How can i throw an error after sometimes maybe 10 seconds if the signin process does not complete?
Thankyou!
In general, it can be achieved with setTimeout.
componentDidMount() {
this.setTimeout( () => {
this.doThisAfterTenSeconds();
},10000);
}
doThisAfterTenSeconds() {
// Do something
}
In this particular scenario,
export const userSignin = (email, password) =>
async dispatch => {
try {
// Auth attempt has started
dispatch({ type: 'auth_attempt_started' })
// Lets add a 10 second timeout
let hasTimedOut = false
setTimeout(() => {
hasTimedOut = true
// Display message here or throw "Connection timed out"
}, 10000)
// Now lets await the authentication
const user = await firebase.auth().signInWithEmailAndPassword(email.trim(), password)
// This code should not be run if auth attempt timed out. If we throw an error the check should not be neccessary...
if (!hasTimedOut)
{
saveUserDataToAsyncStorage(user)
if (!TASKS_SORT_BY && !TASKS_SORT_ORDER)
dispatch(getTasksSortData(user.user.uid))
if (!EMPLOYEES_SORT_BY && !EMPLOYEES_SORT_ORDER)
dispatch(getEmployeesSortData(user.user.uid))
if (!ACCOUNTS_SORT_BY && !ACCOUNTS_SORT_ORDER)
dispatch(getAccountsSortData(user.user.uid))
goToMain()
setTimeout(() => {
dispatch({
type: 'user_signedin',
payload: user
})
}, 100);
}
}
catch (err) {
dispatch({
type: 'auth_error',
payload: err.toString()
})
}
}