I am using axios in an action and trying to call that action with a chaining action. I will show what I am trying to do here:
this.props.fetchOffers().then(() => {
this.props.filter(this.props.filterOption);
});
But I get an error: Cannot read property 'then' of undefined.
What I do not get is that right below this function I have another action that is doing this exact same thing and working just fine.
this.props.sortOffers(value).then(() => {
this.props.filter(this.props.filterOption);
});
Here is a working version of this.
Here is the actions file:
import axios from 'axios';
import { reset } from 'redux-form';
import { FETCH_OFFERS, SORT_OFFERS, FETCH_OFFER, GET_FILTER, PAYMENT_TYPE } from './types';
export function paginateOffers(indexPosition, numberOfItems) {
return (dispatch) => {
axios
.get('/API/offers/pagination', {
params: {
position: indexPosition,
number: numberOfItems,
},
})
.then((response) => {
dispatch({ type: FETCH_OFFERS, payload: response.data });
})
.catch((error) => {
console.error(error);
});
};
}
export function fetchOffers() {
return dispatch => {
axios
.get('/API/offers')
.then((response) => {
dispatch({ type: FETCH_OFFERS, payload: response.data });
})
.catch((err) => {
console.error(err);
});
};
}
export function fetchOffer(id) {
return (dispatch) => {
axios
.get(`/API/offers/${id}`)
.then((response) => {
dispatch({ type: FETCH_OFFER, payload: response.data.result });
})
.catch((err) => {
console.error(`ERROR: ${err}`);
});
};
}
export function sortOffers(params) {
const { price, title, category, type } = params;
return dispatch =>
axios
.get('/API/offers/sort', {
params: { price, title, category, type },
})
.then((response) => {
dispatch({
type: SORT_OFFERS,
payload: response.data,
sortOptions: params,
});
dispatch({
type: PAYMENT_TYPE,
payment: type,
});
dispatch(reset('sorter'));
})
.catch((err) => {
console.error(err);
});
}
export function getFilterOption(option) {
return (dispatch) => {
dispatch({
type: GET_FILTER,
option,
});
};
}
You aren't returning a promise in your fetchOffers action creator. Notice the subtle difference in how you've declared your fat-arrow function.
Try this:
export function fetchOffers() {
return dispatch =>
axios
.get('/API/offers')
.then((response) => {
dispatch({ type: FETCH_OFFERS, payload: response.data });
})
.catch((err) => {
console.error(err);
});
}
Related
I need to upload multiple images but I also need to upload them one by one.
I wanted to upload them sequentially. First, you need to wait for the previous API response before calling another API response. How will I do it?
Currently is that I'm calling them in parallel. Whoever upload image API response has finished first, will be displayed.
export const uploadPhotos =
({ photos, size, controller }) =>
async (dispatch) => {
await Promise.all(
photos.forEach(async (photo, index) => {
const formData = new FormData();
formData.append("photo", photo);
dispatch({ type: constants.UPLOAD_PHOTOS_START, size });
try {
const response = await axios.post(
`${API_URL}/photos/upload`,
formData,
{
onUploadProgress({ loaded, total }) {
dispatch(setUploadProgress({ id: index, loaded, total }));
},
signal: controller.signal,
}
);
dispatch({
type: constants.UPLOAD_PHOTOS_SUCCESS,
payload: response.data,
});
} catch (error) {
dispatch({
type: constants.UPLOAD_PHOTOS_FAILURE,
payload: error,
});
}
})
);
};
export const setUploadProgress = (progress) => ({
type: constants.SET_UPLOAD_PROGRESS,
payload: progress,
});
export const resetUploadData = () => ({
type: constants.RESET_UPLOAD_DATA,
});
export const setOverallSize = (data) => ({
type: constants.SET_OVERALL_SIZE,
payload: data,
});
First: await Promise.all(photos.forEach(async () => {})) will have no effect.
forEach does not return a value so you want .map instead.
But for sequential calls, something like this is preferred:
export const uploadPhotos =
({ photos, size, controller }) =>
async (dispatch) => {
for (const [index, photos] of photos.entries()) {
const formData = new FormData();
formData.append("photo", photo);
dispatch({ type: constants.UPLOAD_PHOTOS_START, size });
try {
const response = await axios.post(
`${API_URL}/photos/upload`,
formData,
{
onUploadProgress({ loaded, total }) {
dispatch(setUploadProgress({ id: index, loaded, total }));
},
signal: controller.signal,
}
);
dispatch({
type: constants.UPLOAD_PHOTOS_SUCCESS,
payload: response.data,
});
} catch (error) {
dispatch({
type: constants.UPLOAD_PHOTOS_FAILURE,
payload: error,
});
}
}
};
I using Spring boot has backend and react-redux has frontend. The problem is where I try too save my data to my db the first click just save my first entity out of seven. After the second click it works normal and afterwards it works normal. I have try useEffect still the same problem.
export const setChecklist = (Checklist) => {return (dispatch) => {
console.log(Checklist);
axios
.post("http://localhost:8081/api/checklist/addList", Checklist)
.then((response) => {
console.log(response);
dispatch({
type: SET_CHECKLIST,
payload: response.data,
});
})
.catch((error) => {
console.log(error);
});
};
};
try this code:
export const setChecklist = async (Checklist) => {
const response = await axios
.post("http://localhost:8081/api/checklist/addList", Checklist)
.then((response) => {
console.log(response);
dispatch({
type: SET_CHECKLIST,
payload: response.data,
});
})
.catch((error) => {
console.log(error);
});
}
useEffect(() => {
setChecklist ()
.then((res) => {
setChecklist(res)
})
.catch((e) => {
console.log(e)
})
}, [])
I am trying to fetch data using API in react.js. My code is like below
import Axios from 'axios';
export const getCountry = () => dispatch => {
return Axios.get('http://treeoverflow.com/api/country/listing/true/111111111111222222222222333333333333444444444444', { crossdomain: true })
.then(response => {
console.log(response.data);
var countryData = response.data;
dispatch({
type: 'getCountries',
payload: countryData
});
})
.catch(function(error) {
console.log('hello');
dispatch({
type: 'getCountryError',
payload: error
});
});
};
export default { getCountry };
I getting below view in Network tab.
But I am not getting result. Is there any issue in this URL 'http://treeoverflow.com/api/country/listing/true/111111111111222222222222333333333333444444444444' ?
Here's my login action code. What am I doing wrong ? As you can see, reducer state update not called.
Please, help me guys!
React - 16.8
Axios Http Client
Node & Mongo Db Backend
export const loginUser = (userData) => {
axios.post(URL + '/api/admin/login', userData)
.then(res => {
return {
type: SIGNIN_USER,
payload: storeData
}
})
.catch(err => {
return {
type: SHOW_MESSAGE,
payload: err.response.data
}
});
};
.then(res => {
return {
type: SIGNIN_USER,
payload: storeData
}
})
Instead of returning res, apply an action to it here. You mentioned changing the state, so something similar:
.then(res => {
this.state.someResult = res;
})
You need to dispatch the action, not just return the object:
const dispatch = useDispatch(); // Assuming you're inside functional component
export const loginUser = (userData) => {
axios.post(URL + '/api/admin/login', userData)
.then(res => {
return dispatch({
type: SIGNIN_USER,
payload: storeData
})
})
.catch(err => {
return dispatch({
type: SHOW_MESSAGE,
payload: err.response.data
})
});
};
Try with this code sample :
export const loginUser = userData => dispatch => (
axios.post(URL + '/api/admin/login', userData)
.then(res => dispatch({ type: SIGNIN_USER, payload: res }))
.catch(err => dispatch({ type: SHOW_MESSAGE, payload: err.response.data }))
)
Make use of Arrow functions it improves the readability of code. No need to return anything in API.fetchComments, Api call is asynchronous when the request is completed then will get the response, there you have to just dispatch type and data.
Below code does the same job by making use of Arrow functions.
export const bindComments = postId => {
return dispatch => {
API.fetchComments(postId).then(comments => {
dispatch({
type: BIND_COMMENTS,
comments,
postId
});
});
};
};
reference link : React-Redux: Actions must be plain objects. Use custom middleware for async actions
sorry in advance for the dumb question. I'm still learning javascript and sometime I have hard time writing simple operations.
I have the following action-creators :
export const fetchgadata = VIEW_ID => (dispatch) => {
dispatch({
type: 'FETCH_DATA_REQUEST',
isFetching:true,
error:null
});
return axios.get("http://localhost:3000/gadata", {
params: {
id: VIEW_ID
}
}).then(response => {
dispatch({
type: 'FETCH_DATA_SUCCESS',
isFetching: false,
data: response.data.rows.map( ([x, y]) => ({ x, y }) )
});
})
.catch(err => {
dispatch({
ype: 'FETCH_DATA_FAILURE',
isFetching:false,
error:err
});
console.error("Failure: ", err);
});
};
export function onSetTimeRange(timerange) {
return {
type: 'SET_TIME_RANGE',
timerange
}
}
What I would like to do is passing the VIEW_ID value to my axios param. So from here ... const fetchgadata = VIEW_ID => (dispatch) => { ... to here ...return axios.get("http://localhost:3000/gadata", { params: { id: VIEW_ID }
}).then(response => ...
How should I wrote my code ?
thanks.