I'm dispatching an action in a react app. Everything is working fine, I'm getting the response I'd expect, just User data and a JWT. My problem is it is still reaching the catch block even though the response is accurate and has a status of 200. Code is below.
export const submitNewUser = (user) => async (dispatch) => {
// debugger;
setLoading();
try {
const res = await axios.post(
`${appConstants.serverRoot}/registerUser/user`,
user,
config
);
console.log("res", res);
dispatch({
type: REGISTER_USER,
payload: res.data,
});
// loadUser();
} catch (error) {
dispatch({
type: USER_ERROR,
payload: error,
});
}
};
Related
This is my auth.js action file where i have created loginUser and loadUser action. Inside loginUser action i have called loadUser() action. But the action loadUser is not being activated after LOGIN_SUCCESS action type.
export const loadUser = () => async (dispatch) => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('/api/auth');
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (err) {
dispatch({
type: AUTH_ERROR,
});
}
};
export const loginUser = (email, password) => async (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const body = JSON.stringify({
email,
password,
});
try {
const res = await axios.post('/api/auth', body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
dispatch(loadUser())
} catch (err) {
const error = err.response.data.msg;
if (error) {
dispatch(setAlert(error, 'danger'));
}
dispatch({
type: LOGIN_FAILED,
});
}
};
i tried so much to figure out the error but i dont know what is interfering with the action due to that only the first action is activated. Please help me. Thanks.
If you're just going to use it for the second action, then you don't need to export loadUser() method.
Just have it be a method in that file and then call it after the dispatch
...
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
loadUser();
...
I was trying to migrate from redux form to react final form, and been facing issues with handling submission errors on redux actions.
My onSubmit looks like:
onSubmit = formValues => {
this.props.login(formValues);
};
And my login action is:
export const login = ({ username, password }) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ username, password });
try {
const res = await axios.post('/api/auth/login', body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
} catch (err) {
dispatch({
type: LOGIN_FAIL
});
}
};
Previously while using redux form, I was using stopSubmit to display the submission errors. What would be the best way to achieve the same thing with react final form?
I managed to solve this soon after.
Had to change onSubmit to:
onSubmit = values => {
let errors = this.props.login(values);
return errors.then(result => result);
};
and the login action creator to:
try {
const res = await axios.post('/api/auth/login', body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
} catch (err) {
dispatch({
type: LOGIN_FAIL
});
return err.response.data;
}
I have a MERN app using redux. My actions look like this:
export const logIn = (logInData) => async (dispatch) => {
try {
const { data } = await api.logIn(logInData);
localStorage.setItem('auth', JSON.stringify(data))
dispatch({
type: LOG_IN,
payload: data
});
} catch (error) {
dispatch({
type: ADD_FLASH_MESSAGE,
payload: error
})
}
}
And my server looks like this
export const logIn = async (req, res) => {
const logInParams = req.body;
const user = await User.findOne({ email: logInParams.email });
if (!user) {
console.log("USER NOT FOUND");
res.status(400).json({
message: "Invalid credentials."
});
}
const passwordMatches = await bcrypt.compare(logInParams.password, user.password);
if (!passwordMatches) {
console.log("WRONG PASSWORD")
return res.status(400).json({
message: "Invalid credentials."
})
}
// Sign in user with jwt
const payload = {
user: {
id: user.id
}
}
jwt.sign(payload, config.get('jwtSecret'), (error, token) => {
if (error) throw error;
console.log('Successfully logged in');
return res.status(200).json({
token: token,
user: user,
loggedIn: true
});
})
}
I'm not able to access my error messages in my actions. I just get error messages like so
POST http://localhost:5000/auth/login 400 (Bad Request)
And my console.log looks like this:
Error: Request failed with status code 400
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
How do I access my custom error messages from my server?
try to get the status as error.status and custom message as error.data.message
your custom error message contain in error.response.data
try change this in your action:
export const logIn = (logInData) => async (dispatch) => {
try {
const { data } = await api.logIn(logInData);
localStorage.setItem('auth', JSON.stringify(data))
dispatch({
type: LOG_IN,
payload: data
});
}
catch (error) {
dispatch({
type: ADD_FLASH_MESSAGE,
payload: **error.response.data**
})
}
}
I am new to redux and
I am now trying to write a login component.
my redux actions is something like this.
export const fetchToken = (params) => {
return (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
return axios
.post(`${baseUri}/api/token`, params, config)
.then((res) => {
dispatch({
type: LOGGED_IN,
payload: res.data,
});
})
.catch((err) => {
console.log(err);
alert('Provided username and password is incorrect');
});
};
};
as you can see I am returning a promise. I try to use it in the component but it's not working.
I am using useDispatch hooks from react-redux
my code look like this
const checkValidate = () => {
if (email.length < 1 || password.length < 1) {
alert('Please fill all the details');
return;
} else {
const params = new URLSearchParams();
params.append('username', email);
params.append('password', password);
params.append('grant_type', 'password');
dispatch(fetchToken(params)).then((res) => {
alert('success')
}).catch((err) => alert('not success'));
}
// navigation.navigate('Home');
};
As you can see I am alerting the success. The problem is that if I write the wrong username and password. The response always goes into success response. It will alert success then It will alert the response from the fetchToken action which is alert('Provided username and password is incorrect'); Is there anything wrong with my code.
And also whenever I try to console.log the then response it will always return undefined
When you do
.then((res) => {
dispatch({
type: LOGGED_IN,
payload: res.data,
});
})
.catch((err) => {
console.log(err);
alert('Provided username and password is incorrect');
});
you remove the error and the result from the chain. If you want them to be passed to the next .then or .catch, you have to return/rethrow it:
.then((res) => {
dispatch({
type: LOGGED_IN,
payload: res.data,
});
+ return res
})
.catch((err) => {
console.log(err);
alert('Provided username and password is incorrect');
+ throw err
});
I have this controller to authenticate a user by their email and password
const authUser = asyncHandler(async (req, res, next) => {
console.log('Hit');
const { email, password } = req.body;
await User.findOne({ email }, async (err1, foundUser) => {
if (err1) {
next(err1);
} else if (foundUser && (await foundUser.matchPasswords(password))) {
res.json({
_id: foundUser._id,
name: foundUser.name,
email: foundUser.email,
token: generateWebToken(foundUser._id),
});
} else {
res.status(401);
next(new Error('Invalid credentials'));
}
});
});
where the mongoose instance method matchPasswords is defined as
userSchema.methods.matchPasswords = async function (enteredPassword) {
return await bcrypt.compare(
enteredPassword,
this.password,
(err, success) => {
console.log(success);
return success;
}
);
};
In the React frontend I have created an action creator loginUser like so
export const loginUser = ({ email, password }) => async (dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const { data } = await axios.post(
'/api/v1/users/login',
{ email, password },
config
);
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.message
? error.response.message.data
: error.message,
});
}
};
However, when I try to login with the wrong credentials or the correct ones I receive this message in the screen and console Uncaught (in promise) TypeError: Cannot read property 'data' of undefined. Above that there is this error main.js?attr=bsXXNSP9r2dL_fbuBOkoev2GjgusyPgY7MC7K-twziLtf_MItBzQdXJ4l_HgsPQw:2699 POST http://localhost:3000/api/v1/users/login 401 (Unauthorized) which made me think maybe it's proxy error because my server is running on port 5000, but the console.log('Hit'); inside the authUser controller is fired when I make the request, which means the request reaches the backend, but there is some uncaught error. Where is my mistake?