else statement is ignored in react - reactjs

when i am trying to perform this task to change password, everything works fine if the response is 200 and it also gives me the pop up window, but if its not it dosent perform the else statement,it like no else. completely ignored.
here is the code
const submitForm = () => {
let form_data = new FormData();
form_data.append('old_password', formValues.oldpass);
form_data.append('new_password', formValues.newpass);
try {
axios.put(baseUrl + '/change-password/', form_data,
{
headers: {
'Authorization': `Token ${token}`
}
}
).then((response) => {
const Swal = require('sweetalert2');
console.log(response.data);
if (response.status === 200) {
Swal.fire(
'Great!',
'Password updated successfully',
'success'
)
}
else {
alert('error ', 'password has not been changed !!');
}
});
} catch (error) {
console.log(error);
}
};
please help i am new to react and i`ve had this issue for days.

Axios throws the response if the status code is something else than 2xx. Which means that if you get e.g. 4xx or 5xx the then clause is not run. Instead you need a catch clause that will handle this case.
.then((response) => {
const Swal = require('sweetalert2');
console.log(response.data);
Swal.fire('Great!', 'Password updated successfully', 'success')
}).catch((response) => {
alert('error ', 'password has not been changed !!');
console.log(error);
});
In this case you can remove try-catch as it won't catch any errors.
Optionally you can await the result of the axios call to have the current catch clause catch the error. Then you'll also need the function to be async.
const submitForm = async () => {
let form_data = new FormData();
form_data.append('old_password', formValues.oldpass);
form_data.append('new_password', formValues.newpass);
try {
await axios.put(baseUrl + '/change-password/', form_data,
{
headers: {
'Authorization': `Token ${token}`
}
}
).then((response) => {
const Swal = require('sweetalert2');
console.log(response.data);
Swal.fire('Great!', 'Password updated successfully', 'success')
});
} catch (error) {
console.log(error);
alert('error ', 'password has not been changed !!');
}
};
https://axios-http.com/docs/handling_errors

Related

Axios does not catch error even not enter in catch block

I am trying to get the error status code that would be 413 in Axios catch block. I have tried different solutions nothing worked for me. Could you please review what is going wrong.
uploadNewDatDocuments(datId, files = [], additionalInfo = {}) {
return new Promise((resolve, reject) => {
let url = new URL(this.baseUrl + this.uploadDocument.replace('{id}', datId));
Object.keys(additionalInfo).forEach(queryParam => url.searchParams.set(queryParam, additionalInfo[queryParam]));
let formData = new FormData();
files.forEach(file => formData.append('files', file));
axios
.post(url.toString(), formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
resolve(response.data);
})
.catch(error => {
console.log("error occurred")
reject(error);
}).finally(error=>{
console.log(error);
})
});
}
Here is my Action code.
export function uploadNewDocuments(datId, additionalInfo = {}, attachments = [], comment = {}) {
return dispatch => {
datService
.uploadNewDatDocuments(datId, attachments, additionalInfo)
.then(response => {
const attachmentsIds = response.map(attachment => attachment.id);
dispatch(
DatCommentActions.addDatNewComment(datId, {
...comment,
message: { ...comment.message, attachments: attachmentsIds }
})
);
})
.catch(error => {
dispatch(MessageActions.showMessage({ message: error.response.data.message }));
console.error(error);
});
};
}
413 Request Entity Too Large is not actually error, its a not successful response and catch wont fire unless there is actual error on response.
What you could do is check response.status and based on that and write own error handling.

Why isn't my catch block catching when I add an if statement?

I have an onSubmit function in my React/Typescript app that will only hit my catch if I don't have my isValid check. I have validation set up on both the client side and server side. The catch displays the validation method from the back end. If isValid is true the form should be submitted. If isValid is false the form should not be submitted and it should hit my catch and display the validation errors.
The following code doesn't catch. It won't submit because it is invalid but it also isn't showing the validation errors from the backend that it should.
const onSubmit = async (event: any) => {
event.preventDefault();
const isValid = formValidation();
const baseUrl = getBackendUrl();
try {
if (isValid)
{
const token = await getAccessTokenSilently();
await axios.post(`${baseUrl}/api/enterprises/${enterpriseId}/users`, formData, {
headers: {
Authorization: `Bearer ${token}`,
}
})
.then(res => {
setFormData(res.data);
close();
})
}
}
catch (error) {
if (error.response) {
setErrors(error.response.data.errors);
}
}
};
If I do this:
const onSubmit = async (event: any) => {
event.preventDefault();
formValidation();
const baseUrl = getBackendUrl();
debugger;
try {
const token = await getAccessTokenSilently();
await axios.post(`${baseUrl}/api/enterprises/${enterpriseId}/users`, formData, {
headers: {
Authorization: `Bearer ${token}`,
})
.then(res => {
setFormData(res.data);
close();
})
}
}
catch (error) {
if (error.response) {
setErrors(error.response.data.errors);
}
}
};
The errors from the backend show, but it will allow me to submit an invalid form.

How to return API data to a separate component - React Native

I am Fetching data from an API in my Native App and displaying it as a List.
Below is my code:
async componentWillMount() {
if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', this.backPressed);
}
this.fetchNotifications();
}
}
async fetchNotifications() {
this.setState({refreshing: true});
const config = getAppConfig();
const cognitoToken = await this.getCognitoToken(config);
if (cognitoToken !== null) {
let headers = await this.getRequestHeaders(cognitoToken);
let body = this.getRequestBody(config);
let notificationUrl = config["notification-retrieve-api"];
return fetch(notificationUrl,
{
method: 'POST',
headers: headers,
body: body
}).then((response) => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong');
}
})
.then((notifications) => {
console.log(JSON.stringify(notifications));
this.setState({
notifications,
error: null,
refreshing: false
});
}).catch((error) => {
this.setState({
notifications: [],
error,
refreshing: false
});
});
}
}
This works fine. I can retrieve the data from the API.
Now I want to separate the API code from my screen component. I will be calling "fetchNotifications" as a function in my screen component. I am trying to do so but it's not working at all.
This is what I'm doing:
async componentWillMount() {
if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', this.backPressed);
}
let response = fetchNotifications();
this.setState({
notifications: response,
error: null,
refreshing: false
})
}
}
async function fetchNotifications() { //now this function is in another component
.
.
.
.
if(cognitoToken !== null) {
let headers = await this.getRequestHeaders(cognitoToken);
let body = this.getRequestBody(config);
let notificationUrl = config["notification-retrieve-api"];
return fetch(notificationUrl,
{
method: 'POST',
headers: headers,
body: body
}).then((response) => {
if (response.ok) {
response.json();
} else {
throw new Error('Something went wrong');
}
})
.then((response) => {
return response;
}).catch((error) => {
this.setState({
notifications: [],
error,
refreshing: false
});
});
}
}
export default fetchNotifications;
Is this way correct? Anyone with a better solution?
My two cents, I always put async task in Promise, including API requests.
// API helper file
export const fetchNotifications = (params) => {
return new Promise(async (resolve, reject)=>{
try{
const headers = getHeaders(params)
const body = getBody(params)
const response = await fetch(notificationUrl,
{
method: 'POST',
headers: headers,
body: body
})
if (response.ok) {
const responseObj = await response.json();
resolve(responseObj)
} else {
throw new Error('Something went wrong');
}
} catch (e) {
// something went wrong
generalHandler(e) // logging etc.
reject(e) // for ui handling
}
}
}
then we can use it everywhere
import { fetchNotifications } from '.../APIHelper'
In your ui file :
componentWillMount() {
fetchNotifications(params)
.then((notifications) => {
console.log(JSON.stringify(notifications));
this.setState({
notifications,
error: null,
refreshing: false
});
}).catch((error) => {
this.setState({
notifications: [],
error,
refreshing: false
});
});
}

Break axios promise chain on catch()

I've centralized all my API calls in a unique file API.js as below:
API.js
Class APIContextProvider extends Component {
async apiCallTest() {
var url = random_url
const options = {
url: url,
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;',
},
};
return await axios(options)
.then(response => {
if (response.status === 200) {
return response.data
}
}).catch(error => {
console.log(error.response.status)
}
);;
}
Then I call my API from another component:
OutsideClass.js
async componentDidMount() {
this.context.apiCallTest().then(data => {
// How can I prevent this then() to run when catch() happens?
});
}
The order is which everything is done is: then().catch().then().
What I want is to prevent the last then(). from happening if a specific error is caught (like 401) since I want global error handling.
Looked everywhere but can't find a solution...
Thank you!
If you want to catch exception globally, then use axios interceptors in your bootstrap file just after
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.interceptors.response.use(
function (response) {
return response;
},
function (error) {
// handle error
if (error.response.status === 422)
return error;
if (error.response.status === 401)
alert(error.response.status + ': ' + error.response.data.message);
});
You can throw the error again in you catch, and it will avoid the then and go to the next catch.
await axios(options)
.then(response => {
if (response.status === 200) {
return response.data
}
}).catch(error => {
if (error.response.status === 401) {
throw error;
}
console.log(error.response.status)
}

React Saga Generator yield call undefined object

So I am using axios to call my server and get response, and tried it with redux-saga but with no success. When I console log inside my axios call I got response, but signInUser in yield call is undefined forever. What can be wrong here?
const signInUserM = async (email, password) => {
await axios
.get("https://localhost:44320/Account/token")
.then(async function(response) {
const { data } = response;
axios.defaults.headers.common = {
Authorization: `Bearer ${data.token}`
};
await axios
.post("https://localhost:44320/Login", {
email: email,
password: password
})
.then(authUser => {
console.log(authUser); // got response
return authUser;
})
.catch(error => {
console.log(error);
return error;
});
})
.catch(error => {
console.log(error);
return error;
});
};
function* signInUserG({ payload }) {
const { email, password } = payload;
try {
const signInUser = yield call(
signInUserM,
email,
password
);
console.log(signInUser); // undefined forever
if (signInUser) {
// never gets here
yield put(userSignInSuccess(signInUser.id));
}
} catch (error) {
console.log(error);
}
}
Thanks for any help!
You forgot return in signInUserM and in front of the other await as well I think.

Resources