Hello it's been 2 weeks since I am learning React and Redux I wanted to know that from my ActionCreators.js file i exported the const postFeedback and imported it in my MainComponent.js But I am getting this error
./src/Components/MainComponent.js
Attempted import error: 'postFeedback' is not exported from '../redux/ActionCreators'.
***This is my ActionCreators.js File
import * as ActionTypes from './ActionTypes';
import {baseUrl} from '../shared/baseUrl';
export const addComment = (comment) => ({
type: ActionTypes.ADD_COMMENT,
payload: comment
});
//////
export const postComment = (dishId, rating, author, comment) => (dispatch) => {
const newComment = {
dishId: dishId,
rating: rating,
author: author,
comment: comment
};
newComment.date = new Date().toISOString();
return fetch(baseUrl + 'comments', {
method: "POST",
body: JSON.stringify(newComment),
headers: {
"Content-Type": "application/json"
},
credentials: "same-origin"
})
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
throw error;
})
.then(response => response.json())
.then(response => dispatch(addComment(response)))
.catch(error => { console.log('post comments', error.message); alert('Your comment could not be posted\nError: '+error.message); });
};
///FEEDBACK
export const postFeedback = (feedback) => (dispatch) => {
const newFeedback = Object.assign({ date: new Date().toISOString() }, feedback);
return fetch(baseUrl + 'feedback', {
method: 'POST',
body: JSON.stringify(newFeedback),
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin'
})
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errorMessage = new Error(error.errorMessage);
throw errorMessage;
}
)
.then(response => response.json())
.then(response => dispatch(addComment(response)))
.catch(error => {
console.log('Post feedback: ' + error.message);
alert('Feedback could not be posted:\n' + error.message)
})
};
//////
export const fetchDishes = () => (dispatch) => {
dispatch(dishesLoading(true));
return fetch(baseUrl + 'dishes')
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(dishes => dispatch(addDishes(dishes)))
.catch(error => dispatch(dishesFailed(error.message)));
}
export const fetchComments = () => (dispatch) => {
return fetch(baseUrl + 'comments')
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(comments => dispatch(addComments(comments)))
.catch(error => dispatch(commentsFailed(error.message)));
};
export const fetchPromos = () => (dispatch) => {
dispatch(promosLoading());
return fetch(baseUrl + 'promotions')
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(promos => dispatch(addPromos(promos)))
.catch(error => dispatch(promosFailed(error.message)));
}
///***Assignment4 where we used all the three actions in this thunk to make effective use of them and also to make the fetch available
export const fetchLeaders = () => (dispatch) => {
dispatch(leadersLoading());
return fetch(baseUrl + 'leaders')
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(promos => dispatch(addLeaders(promos)))
.catch(error => dispatch(leadersFailed(error.message)));
}
export const commentsFailed = (errmess) => ({
type: ActionTypes.COMMENTS_FAILED,
payload: errmess
});
export const addComments = (comments) => ({
type: ActionTypes.ADD_COMMENTS,
payload: comments
});
export const dishesFailed = (errmess) => ({
type: ActionTypes.DISHES_FAILED,
payload: errmess
});
export const promosLoading = () => ({
type: ActionTypes.PROMOS_LOADING
});
export const promosFailed = (errmess) => ({
type: ActionTypes.PROMOS_FAILED,
payload: errmess
});
export const addPromos = (promos) => ({
type: ActionTypes.ADD_PROMOS,
payload: promos
});
export const addDishes = (dishes) => ({
type: ActionTypes.ADD_DISHES,
payload: dishes
});
export const dishesLoading = () => ({
type:ActionTypes.DISHES_LOADING
});
/////***Assignement4
//basically we created the actions here now to make them be used using thunk
export const addLeaders = (leaders) => ({
type: ActionTypes.ADD_LEADERS,
payload: leaders
});
///
export const leadersLoading = () => ({
type: ActionTypes.LEADERS_LOADING,
});
export const leadersFailed = (errmess) => ({
type: ActionTypes.LEADERS_FAILED,
payload: errmess
});
//ADDED THREE NEW ACTIONS NOW TO FETCH THUNK THEM
***This is my MainComponent.js file
import { postComment, fetchDishes, fetchComments, fetchPromos ,fetchLeaders ,postFeedback} from '../redux/ActionCreators';
const mapDispatchToProps = dispatch => ({
postFeedback: (firstname, lastname, telnum, email, agree, contactType, message) =>
dispatch(postFeedback(firstname, lastname, telnum, email, agree, contactType, message))
});
I suggest to update the mapDispatchToProps like this:
const mapDispatchToProps = dispatch => {
return {
postFeedback: () => dispatch(postFeedback),
}
}
Then call it in your component like this:
this.props.postFeedback(firstname, lastname, ...other args)
Related
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.
Initially I write my code with promise based script .then().catch
But when I tried to change it into the async await function. Its not working anymore.
Please someone help me with this.
My Old Code Which is working
export const fetchToken = (params) => {
return (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
return axios
.post(`/api/token`, params, config)
.then((res) => {
tokenData = res.data.access_token;
dispatch({
type: LOGGED_IN,
payload: res.data,
});
})
.catch((err) => {
console.log(err);
alert('Provided username and password is incorrect');
throw err;
});
};
};
As you can see in the above code the function is returning a promise. But When I try to change it into async await
My simulator is give me Unexpected reserved work await Error
Here is my async await code in redux
export const fetchToken = async (params) => {
return (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
try {
const response = await axios.post(`/api/token`, params, config);
const data = await response.json();
tokenData = data.access_token
dispatch({ type: LOGGED_IN, payload: res.data})
} catch {
console.log(err);
alert('Provided username and password is incorrect');
}
};
};
Your async is applied to the wrong function, it should be on the dispatch function
export const fetchToken = (params) => (
async (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
try {
const response = await axios.post(`/api/token`, params, config);
const data = await response.json();
tokenData = data.access_token
dispatch({ type: LOGGED_IN, payload: res.data})
} catch {
console.log(err);
alert('Provided username and password is incorrect');
}
};
);
NB: I've removed the braces; arrow function return is implied https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
I am back with a newbie question, eventually i have built a function too complex with my promises, but maybe someone has some insight in why the setSiteAdded/Updated and setArticlesAdded/Updated functions are not working in the correct way for me here. I want to count up, all directly saved and updated elements of the fetched data from my API.
I am using typeORM locally on my ios device with sqlite.
Here is my code:
const saveToDB = (type, element) => {
return new Promise(async (resolve, reject) => {
if (type === 'site') {
let site = new Site();
site.created = element.CREATED;
site.sitenum = element.SITENUM;
site.title = element.TITLE;
site.updated = element.UPDATED;
let siteRepository = getRepository(Site);
siteRepository.findOne({ where: { sitenum: site.sitenum } })
.then((foundSite) => {
site.id = foundSite.id;
if (foundSite.updated !== site.updated) {
siteRepository.update(foundSite.id, site)
.then((savedSite) => {
console.log("Site has been updated!", savedSite);
setSitesUpdated(sitesUpdated + 1);
resolve(savedSite);
}).catch((error) => {
console.log("Error: ", error);
reject();
});
} else {
resolve();
}
})
.catch(() => {
siteRepository.save(site)
.then((savedSite) => {
console.log("Site has been saved!", savedSite);
setSitesAdded(sitesAdded + 1);
resolve(savedSite);
})
.catch((error) => {
console.log("Error: ", error);
reject();
});
});
} else if (type === 'article') {
let article = new Article();
article.created = element.CREATED;
article.updated = element.UPDATED;
article.artnum = element.ARTNUM;
article.ean = element.EAN;
article.title1 = element.TITLE1;
article.title2 = element.TITLE2;
article.unit = element.UNIT;
article.price = element.PRICE;
article.quantity = element.QUANTITY;
let articleRepository = getRepository(Article);
articleRepository.findOne({ where: { artnum: article.artnum } })
.then((foundArticle) => {
article.id = foundArticle.id;
if (foundArticle.updated !== article.updated) {
articleRepository.update(foundArticle.id, article)
.then((savedArticle) => {
console.log("Article has been updated!", savedArticle);
setArticlesUpdated(articlesUpdated + 1);
resolve(savedArticle);
})
.catch((error) => {
console.log("Error: ", error);
reject();
});
} else {
resolve();
}
})
.catch(() => {
articleRepository.save(article)
.then((savedArticle) => {
console.log("Article has been saved!", savedArticle);
setArticlesAdded(articlesAdded + 1);
resolve(savedArticle);
})
.catch((error) => {
console.log("Error: ", error);
reject();
});
});
}
})
}
const fetchDataFromServer = () => {
return new Promise(async (resolve, reject) => {
setLoading(true);
Promise.all([
new Promise(async (resolve, reject) => {
try {
let counter = 0;
let sites = await fetch(
host + 'sites', { method: 'GET', headers: { token: token } }
)
let sitesJson = await sites.json();
Promise.all(sitesJson.data.map(async (element) => {
counter++;
return saveToDB('site', element)
}))
.then(() => {
setSitesAdded(counter);
resolve();
})
.catch(() => reject());
} catch (error) {
console.error(error);
}
}),
new Promise(async (resolve, reject) => {
try {
let articles = await fetch(
host + 'articles', { method: 'GET', headers: { token: token } }
)
let articlesJson = await articles.json();
Promise.all(articlesJson.data.map(async (element) => {
return saveToDB('article', element)
}))
.then(() => resolve())
.catch(() => reject());
} catch (error) {
console.error(error);
}
})
])
.then(() => resolve())
.catch(() => reject())
})
}
my list of users is undefined when i try to console.log it.
Maybe i didn't get something ?
I'd like to get my list of users from my api who works (tested with postman) and put it into the console next i'd like to map my users to show it on the app
class Test extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
}
}
componentDidMount() {
console.log("component did mount");
fetch("/user/list")
.then(res => {
return res.json();
})
.then(users =>
this.setState({users}, () =>
console.log("list of users => " + users)));
}
render() {
return (
<div className="form">
<ul>
{this.state.users.map((user) =>
<li key="user._id">{ user.name }</li>
)}
</ul>
</div>
);
}
} export default Test;
Thanks for help !
You are calling res.json() rather than returning res.json() from the first then on your fetch call
I've found this pattern to be helpful:
fetch(url)
.then(res => res.ok ? res.json() : Promise.reject())
As your code is now, users (the parameter in the second then would be undefined, because you are not returning anything from the first then
you have to return the res.json() to use it in the next .then()
.then(res => {
res.json();
})
should be
.then(res =>
res.json();
)
Or
.then(res => {
return res.json();
})
https://javascript.info/promise-chaining
You should be passing your res into res.json() and returning the results into your state.
componentDidMount() {
console.log("component did mount");
fetch("/user/list")
.then(res => res.json())
.then(users =>
this.setState(users,
() => {
console.log("list of users => " + users)
})
);
}
Michael Jasper response help me so much!
I found that fetch with GET method does not work if we pass any request body.
the full example is here
https://github.com/alexunjm/todo-list-react
const buildRequestOptions = ({
method = "GET",
raw = null, // I had my error here!, with GET raw need to be null
customHeaders = {name: 'value'},
}) => {
var myHeaders = buildHeaders(customHeaders);
var requestOptions = {
method,
headers: myHeaders,
body: raw,
redirect: "follow",
};
return requestOptions;
};
const listTasks = () => {
const url = `${uriBase}/task/sample`;
const requestOptions = buildRequestOptions({
customHeaders: { "Content-Type": "application/json" },
});
return fetch(url, requestOptions);
}
const asyncFn = ({
promiseToWait,
pendingFn,
successFn,
errorFn,
}) => {
return (dispatch) => {
dispatch(pendingFn());
promiseToWait
.then((res) => {
if (res.ok) {
return res.json();
}
// handled from server status 422 and 401
if (res.status === 422) {
// error message on body from server
return res.json();
}
if (res.status === 401) {
// custom error message hardcoded
return {errors: {action: 'no authorized'}}
}
console.log("http response no controlled", res);
return Promise.reject();
})
.then((body) => {
if (body.errors) {
const errors = Object.keys(body.errors).map(
(key) => key + " " + body.errors[key]
);
dispatch(errorFn(errors.join("; ")));
} else {
dispatch(successFn(body));
}
return body;
})
.catch((error) => {
console.log("error", error);
dispatch(errorFn("Unavailable server connection"));
});
};
};
const queryTasks = () => {
return asyncFn({
promiseToWait: listTasks(),
pendingFn: apiPending,
successFn: apiSuccessList,
errorFn: apiError,
});
}
i am beginner react-native programmer . I am trying to return the responseJSON in a fetch function . I know it is asynchronous and will return promise, thus I need to use .then() , but when it says undefined is not an object.
here is the code
auth.js
export const onVerify = (email,password,navigation) => {
console.log('Verifying');
fetch('xxx',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'email=' + email + '&password=' + password
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.status == '200') {
Alert.alert(
'Login Successful',
'Welcome Home'
);
let data = {
name: responseJson.name,
id : responseJson.id
};
onSignIn();
return responseJson
}
in my signin.js
export default class SignIn extends React.Component{
step(){
onVerify(this.state.email,this.state.password,this.props.navigation).then(
function(data) {
console.log(data);
}
);
}
As said by #teivaz on the comment, your onVerify function returns nothing. Because the fetch call is asynchronous. So what you can do is return a Promise from onVerify then you'll be able to resolve it from step function.
This is how you can implement this,
export const onVerify = (email,password,navigation) => {
return new Promise((resolve, reject) => {
fetch('endpoint',
{
method,
headers,
body,
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.status == '200') {
Alert.alert(
'Login Successful',
'Welcome Home'
);
let data = {
name: responseJson.name,
id : responseJson.id
};
onSignIn();
resolve(responseJson)
}
})
.catch(err => reject(err));
}
}
Also, make sure to catch the errors if any in step function.
export default class SignIn extends React.Component{
step(){
onVerify(this.state.email,this.state.password,this.props.navigation).then(
function(data) {
console.log(data);
}
)
.catch(err => console.log('Error occured', err));
}
}