I have this weird error in my React app at the moment. I am sending an api request and I want to do something if it succeeds and something else if I get an error back. The api requests succeeds, the post is getting approved, but the catch clause is executed instead of then.
Can you see something in this code that might make that happen?
The request which I am talking about is the Request.post one... the large one that ecompasses a few other requests.
export const approvePostSubmission = (post, date) => dispatch => {
const label = `${post.campaign_product_name} on ${moment(date).format('LL')}`;
if (post.post_type === 3) {
dispatch(sendGoogleEvent(GOOGLE_EVENT.STORY.APPROVE, label));
} else {
dispatch(sendGoogleEvent(GOOGLE_EVENT.POST.APPROVE, label));
}
dispatch({
type: APPROVE_POST_PENDING,
});
return Request.post(
API_ENDPOINT.POST_APPROVE(post.id),
{ publish_at: date },
false
)
.then(response => {
const { selectedContent } = store.getState().inbox;
dispatch(getUserWallet());
dispatch({
type: APPROVE_POST_SUCCESS,
});
const getPostTypeText = post_type => {
switch (post_type) {
case 3:
return 'Story';
case 4:
return 'IGTV Post';
case 5:
return 'Carousel';
case 6:
return 'IG Live';
default:
return 'Post';
}
};
const postType = getPostTypeText(selectedContent.post.post_type);
setTimeout(() => {
toast.show(
<p>
{`Woo! You approved a ${postType}! It will be published on `}
<RouterLink
to="/calendar"
color="#0dd36b"
onClick={e => toast.hide()}
>
{`${moment(date).format('LL')} 🙌`}
</RouterLink>
</p>,
{
type: 'success',
dismiss: true,
}
);
}, 100);
// Send slack bot message
Request.post(`${SLACKBOT.URL}/new-post`, {
post_status: 1,
post_type: selectedContent.post.post_type,
post_id: selectedContent.post.id,
campaign_name: selectedContent.post.campaign_product_name,
influencer_id: selectedContent.influencer.id,
influencer_name: selectedContent.influencer.full_name,
campaign_id: selectedContent.post.campaign_id,
post_image: selectedContent.post.image_url,
slack_channel: SLACKBOT.CHANNELS.NEW_POST,
})
.then(data => {})
.catch(err => console.error(err));
return response;
})
.catch(err => {
setTimeout(() => {
dispatch({
type: APPROVE_POST_FAIL_SHOW_ERR,
payload: !!err.response
? err.response.data.message
: 'Unable to approve post!',
});
!!err.response &&
toast.show(
`${err.response.data.message || err.response.data.error} 🚫`,
{ type: 'fail' }
);
setTimeout(() => {
dispatch({
type: APPROVE_POST_FAIL,
});
}, 3000);
}, 500);
});
};
Related
I have been working on a project where I am trying to update my selected data but Axios didn't Update it even after giving a success msg.
User Response it returns from axios:-
completed: true
date: "2021-02-28"
mupp_path: "PATH 1 - LIVING YOUR WHY - Build/Apply/Inspire/Spread (BAIS) – Finding & Achieving Meaning and Purpose in work and life"
project_name: "Design and Test the Training Content for the i-Infinity 3 verticals "
selected: true
task_id: 14
task_name: "This is adding a new task to chekc full inbox functionality "
task_type: "THIS_WEEK"
Actions.js
export const taskTodayUnselect = (id) => async (dispatch) => {
try {
dispatch({ type: types.UNSELECTED_TASK_TODAY_REQUEST });
const { data } = await axios.put(
selectTaskForToday,
{
task_id: id,
selected: false,
},
{
headers: {
Authorization: `JWT ${token}`,
},
}
);
if (data) {
return dispatch({ type: types.UNSELECTED_TASK_TODAY_SUCCESS, payload: data });
}
} catch (error) {
return dispatch({ type: types.UNSELECTED_TASK_TODAY_FAILURE, payload: error });
}
};
thisweek.js
export default function ThisWeek() {
const unselectTaskTodayAPI = (id) => {
dispatch(taskTodayUnselect(id)).then((response) => {
let result = response.payload;
console.log(result);
if (result.success === 'true') {
notifySuccess(result.message);
fetchTaskData(categoryID);
}
});
};
const selectTask = (item) => {
if (item.selected) {
unselectTaskTodayAPI(item);
console.log('unselect');
} else {
selectTaskTodayAPI(item.task_id);
}
};
return (
<TaskDataComponent
item={item}
key={item.task_id}
label="This Week"
selectTask={selectTask}
/>
);
Don't Worry about the TaskDataComponent , it only handle the onClick function which invoke the selectedTask function
This has more to do with promises and async/await than the package I am using but in any event, the package is react-native-background-upload and I have an issue with getting back the response from inside of the 'completed' event listener. I think my understanding of how these promises resolve might be wanting but I need to return the response from the server after the upload is complete. The example file provided here mostly caters for logging to the console, not returning data from the server.
async submit() {
const responsefromUpload = await this.videoUploader().then((data) => data);
console.log(responsefromUpload);
}
from which I call the function below
videoUploader() {
const { video } = this.state;
video.uri = Platform.OS == 'android' ? video.uri.replace('file://', '') : video.uri;
const options = {
url: 'https://upload.wistia.com',
path: video.uri,
method: 'POST',
field: 'file',
type: 'multipart',
};
return Upload.startUpload(options).then((uploadId) => {
console.log('Upload started');
Upload.addListener('progress', uploadId, (data) => {
console.log(`Progress: ${data.progress}%`);
});
Upload.addListener('error', uploadId, (data) => {
console.log(`Error: ${data.error}%`);
});
Upload.addListener('cancelled', uploadId, (data) => {
console.log('Cancelled!');
});
Upload.addListener('completed', (data) => {
// data includes responseCode: number and responseBody: Object
console.log('Completed!');
return data.resporesponseBody; // this return doesn't work
});
}).catch((err) => {
console.log('Upload error!', err);
});
}
Any assistance will be greatly appreciated.
wrap the code in .then((uploadId) => { ... } in a "new Promise" - resolve the promise in completed handler ... resolve(data.resporesponseBody);
i.e.
videoUploader() {
const {video} = this.state;
video.uri = Platform.OS == 'android' ? video.uri.replace('file://', '') : video.uri;
const options = {
url: 'https://upload.wistia.com',
path: video.uri,
method: 'POST',
field: 'file',
type: 'multipart',
};
return Upload.startUpload(options)
.then(uploadId => new Promise((resolve, reject) => {
console.log('Upload started');
Upload.addListener('progress', uploadId, data => {
console.log(`Progress: ${data.progress}%`);
});
Upload.addListener('error', uploadId, data => {
console.log(`Error: ${data.error}%`);
reject(data);
});
Upload.addListener('cancelled', uploadId, data => {
console.log('Cancelled!');
reject(data); //?
});
Upload.addListener('completed', data => {
// data includes responseCode: number and responseBody: Object
console.log('Completed!');
resolve(data.responseBody);
});
}))
.catch(err => {
console.log('Upload error!', err);
});
}
you can the wrap startUpload .then block code inside a Promise and resolve it on the completion of file upload.
function videoUploader() {
const { video } = this.state;
video.uri = Platform.OS == 'android' ? video.uri.replace('file://', '') : video.uri;
const options = {
url: 'https://upload.wistia.com',
path: video.uri,
method: 'POST',
field: 'file',
type: 'multipart'
};
return Upload.startUpload(options).then(uploadId => {
const uploadCompletionPromise = new Promise(function(resolve, reject) {
Upload.addListener('progress', uploadId, data => {
console.log(`Progress: ${data.progress}%`);
});
Upload.addListener('error', uploadId, data => {
console.log(`Error: ${data.error}%`);
});
Upload.addListener('cancelled', uploadId, data => {
console.log('Cancelled!');
});
Upload.addListener('completed', data => {
console.log('Completed!');
resolve(data.resporesponseBody);
});
});
return uploadCompletionPromise
.then(response => ({ success: true, data: response }))
.catch(error => ({ success: false, error }));
}).catch((error) => {
console.log('Upload error!', error);
return { success: false, error }
});
}
I'm working with React Redux, and I'm trying to call a function inside another function on my actions file. The problem is It only work if I take the dispatch part of the function.
I wan't to call updateToken() from askForUser() but it will only work if I take the dispatch part from updateToken(). Also when i call askForUser() from askForUser() it won't work either.
const updateToken = (token) => dispatch => {
console.log(token)
dispatch({
type: UPDATE_TOKEN,
payload: token
})
}
const askForUser = (token) => dispatch => {
dispatch({ type: ASKING_FOR_DATA })
axios.get(API.GET_USER, {
params: {
token
}
}).then((response) => {
if (response.data.status === 1) {
dispatch({ type: ASK_FOR_USER, payload: response.data.user })
} else if (response.data.status === 2) {
updateToken(response.data.token)
//console.log(hola2())
} else {
NotificationManager.error('Error consiguiendo usuario')
dispatch({ type: ERROR_HANDLER })
}
}).catch((err) => {
console.log(err)
dispatch({ type: ERROR_HANDLER })
})
}
you'll have to dispatch it :
else if (response.data.status === 2) {
dispatch(updateToken(response.data.token)); // dispatch the function here
}
I want to update status, but when I want to do the 'put' it's not working cause axios in axios.put is not define. Can you help me please.
getAbsencesByRequestId(reqId) {
axios.get(REQUESTID_URL + reqId).then(response => {
this.collaboId = response.data[0].collabId;
this.beginDate = response.data[0].startDate;
this.finishDate = response.data[0].endDate;
this.reason = response.data[0].type;
}, (error) => {
console.log(error.response.status)
}) axios.put(REQUEST_URL + reqId, {
collabId: this.collaboId,
startDate: this.beginDate,
endDate: this.finishDate,
status: 'VALIDATED',
type: this.reason
})
},
You should manage properly the order of your requests
axios.get(url /*optional payload and headers*/).then((getResponse) => {
//do GET stuff with response
}).then(() => {
//do PUT call
axios.put(url, /*optional payload and headers*/).then((putResponse) => {
//do PUT stuff with response
})
}).catch((e) => {
//handle the error
})
I am trying to chain dispatches with redux-thunk. I have 2 action creator as below:
getResourceLinks:
export const getResourceLinks = () => {
return dispatch => {
let req = {
url: getRootUrl(),
header: {
Accept: 'application/json'
}
};
return request(req).then(res => {
dispatch({
type: ActionTypes.RESOURCE.LOAD_URL_SUCCESS,
payload: res.body
});
}).catch(err => {
dispatch({
type: ActionTypes.RESOURCE.LOAD_URL_ERROR,
payload: err
});
});
}
};
and loadAppliances:
export const loadAppliances = () => {
return (dispatch, getState) => {
return dispatch(getResourceLinks()).then(res => {
const {resources} = getState();
let req = {
url: getResourceLink(Resources.Appliances, res.body),
header: {
Accept: 'application/json'
}
};
request(req).then(res1 => {
dispatch({
type: ActionTypes.APPLIANCE.LOAD_SUCCESS,
payload: res1.body
});
}).catch(err => {
dispatch({
type: ActionTypes.APPLIANCE.LOAD_ERROR,
payload: err
});
});
});
};
};
I am facing with an error: Uncaught TypeError: Cannot read property 'then' of undefined at line 3 in loadAppliances action. Promise was returned correctly, wasn't it? Am I doing wrong something? I've seen carefully examples of thunk-redux but I don't still find out what was wrong.
Update. Here is request:
import superagent from 'superagent';
import superagentPromisePlugin from 'superagent-promise-plugin';
import {RequestMethods} from '../constant';
const request = ({url, method = RequestMethods.GET, param, body, header}) => {
let methodStr;
switch (method) {
case RequestMethods.POST:
methodStr = 'POST';
break;
case RequestMethods.PUT:
methodStr = 'PUT';
break;
case RequestMethods.DELETE:
methodStr = 'DELETE';
break;
default:
methodStr = 'GET';
break;
}
let req = superagent(methodStr, url).use(superagentPromisePlugin);
//set header
if (header) {
req.set(header)
}
//set param
if (param) {
req.query(param)
}
//set body
if (body) {
req.send(body)
}
return req;
};
export default request;
The problem here is that dispatch does not return your promise. It actually returns the dispatched action itself. (reference).
return dispatch(getResourceLinks()).then(res => {
^--- this is the problem
The way I would approach this is to dispatch an action after your first successful call and store any pertinent information in the state, then dispatch the next call and store its response.
Example
const getResourceLinks = () => {
return request({
url: getRootUrl(),
header: {
Accept: 'application/json'
}
});
};
const getAppliances = (appliances) => {
return request({
url: getResourceLink(Resources.Appliances, appliances),
header: {
Accept: 'application/json'
}
})
};
export const loadAppliances = () => {
return (dispatch, getState) => {
getResourceLinks()
.then(res => {
dispatch({
type: ActionTypes.RESOURCE.LOAD_URL_SUCCESS,
payload: res.body
});
return getAppliances(res.body)
.then(res1 => {
dispatch({
type: ActionTypes.APPLIANCE.LOAD_SUCCESS,
payload: res1.body
});
})
.catch(err => {
dispatch({
type: ActionTypes.APPLIANCE.LOAD_ERROR,
payload: err
});
});
})
.catch(err => {
dispatch({
type: ActionTypes.RESOURCE.LOAD_URL_ERROR,
payload: err
});
});
}
}
You also might want to take a look at redux-saga