(Multiple) Axios Post requests/params question - javascript

This is a multipart question (and coincidentally my first here on Stack!). To preface, I'm building a site with a Rails backend and a Vue.js frontend.
My problem is with an Axios POST request. I am attempting to send two POST requests with one click of the submit button. I have a "Trips" controller and a "User_Trips" controller - the later of which functions as a join to other tables in my database. In order for a newly created trip to show up, a new user_trip needs to be created too.
My trip posts just fine and shows up when I look for it in Postico, but my user_trip does not post successfully, and I think it's because I'm struggling to determine how to pass the recently created trip's id through as the param needed to create a user_trip. Here is a section of the code I'm working on from Vue.js:
<script>
import axios from "axios";
export default {
data: function() {
return {
trips: [],
errors: [],
name: "",
country: "",
state: "",
city: "",
postal_code: "",
start_date: "",
end_date: "",
image: "",
trip: this.trip
};
},
mounted: function() {
// axios.get("http://localhost:3000/api/trips").then(
// function(response) {
// console.log(response);
// this.trips = response.data.trips;
// }.bind(this)
// );
},
methods: {
submit: function() {
var params = {
name: this.name,
country: this.country,
state: this.state,
city: this.city,
postal_code: this.postal_code,
start_date: this.start_date,
end_date: this.end_date,
image: this.image
};
axios
.post("http://localhost:3000/api/trips", params)
.then(response => {
axios.get("http://localhost:3000/api/trips").then(
function(response) {
console.log(response);
this.trips = response.data.trips;
}.bind(this)
);
})
.catch(error => {
this.errors = error.response.data.errors;
});
var paramsTwo = {
trip_id: this.trip.id
};
axios
.post("http://localhost:3000/api/usertrips", paramsTwo)
.then(response => {
this.$router.go("/home");
})
.catch(error => {
this.errors = error.response.data.errors;
});
}
}
};
</script>
Here is the error message I receive in the console log:
Uncaught TypeError: Cannot read property 'id' of undefined and I'm thinking it's because I'm not selecting the right trip from the array...BUT when I look at the GET request in the log, the newly created trip doesn't show up - it's only visible my database. Any helpful suggestions are most appreciated!!
- Thanks

Figured it out! A big thanks to the helpful commenters and answerers.
<script>
import axios from "axios";
export default {
data: function() {
return {
trips: [],
errors: [],
name: "",
country: "",
state: "",
city: "",
postal_code: "",
start_date: "",
end_date: "",
image: "",
};
},
mounted: function() {
},
methods: {
submit: function() {
var params = {
name: this.name,
country: this.country,
state: this.state,
city: this.city,
postal_code: this.postal_code,
start_date: this.start_date,
end_date: this.end_date,
image: this.image
};
axios
.post("http://localhost:3000/api/trips", params)
.then(response => {
console.log(response);
this.trip = response.data;
var paramsTwo = {
trip_id: this.trip.id
};
axios
.post("http://localhost:3000/api/usertrips", paramsTwo)
.then(response => {
this.$router.go("/home");
})
.catch(error => {
this.errors = error.response.data.errors;
});
}
);
}
}
};
</script>

The code is breaking at the paramsTwo line and that's why your second post won't work. Make sure that the object returned by your API has an id property. Some DBs return a _id property instead of id.

Related

How to parse a property of a react object

I am working in react and have a resonse ( ReviewerService.getReviewers()) that returns an array of values:
0: {id: 1, firstName: 'John', lastName: 'Doe', email: 'johndoe#aol.com', responses: '{"q1":"yes","q2":"no","q3":"yes","rating":4}'}
1: {id: 2, firstName: 'bob', lastName: 'jefferson', email: 'bob#aol.com', responses: '{"q1":"bob","q2":"yes","q3":"yes","rating":5}'}.
If this.state = { reviewers: [] }.
How do i pass the response data into reviewers and parse the responses property at the same time? Therefore, then I can access these properties of the responses easily.
class ListReviewsComponent extends Component {
constructor(props) {
super(props);
this.state = {
reviewers: [],
};
}
async componentDidMount() {
await ReviewerService.getReviewers().then((res) => {
this.setState({ reviewers: res.data });
});
this.setState({ reviewers.responses: JSON.parse(this.state.reviewers.responses)}); // error
}
can this work
async componentDidMount() {
try {
const res = await ReviewerService.getReviewers();
// got the data
const reviewers = res.data;
// not parse the responses for each reviewer
const mappedReviewers = reviewers?.map(reviewer => {
try {
const parsedResponses = JSON.parse(reviewer.responses)
// do you need to convert parsedResponses to an array ??
return {
...reviewer,
responses: parsedResponses
}
} catch(error) {
return {
...reviewer,
responses: [] //
}
}
});
this.setState({ reviewers: mappedReviewers})
} catch (error) {
// log errors
}
}
Hope this helps you to sort out the issue
I think that you array returned by
ReviewerService.getReviewers()
should be in json format, treated or parsed, before, setted in setState:
data = [ {id: 1, firstName: 'John', lastName: 'Doe', email: 'johndoe#aol.com', responses: '{"q1":"yes","q2":"no","q3":"yes","rating":4}'}
,{id: 2, firstName: 'bob', lastName: 'jefferson', email: 'bob#aol.com', responses: '{"q1":"bob","q2":"yes","q3":"yes","rating":5}'} ];
Then you do this, putting array in a json treated object format
async componentDidMount() {
await ReviewerService.getReviewers().then((res) => {
this.setState({ reviewers: res.data });
});
When you do:
this.setState({ reviewers: res.data });
You area putting on this.state.reviewers, all list and all objects nested in.
You could access this.state on this component like this method below:
getResponsesOfReviewersOnArrayByIndex = (index) => {
return this.state.reviewers[index].responses
}
Or just in some method access,
this.state.reviewers[i].firstName
You can try this to understand better the JSON parse function:
const reviewersData = '[{"name":"neymar"}, {"name":"junior"}]';
const reviewers = JSON.parse(reviewersData);
console.log(reviewers[0].name);
In this W3Schools to see more examples of JSON.parse()
Hope this helps.

Unexpected asynchronous action in "" computed property vue/no-async-in-computed-properties Vue3

I am developing my project with Vue3 , I am getting this error while running, here is my whole code . Can someone help me fix it. Thank you guys
<script>
import axios from 'axios';
export default {
name: "RegisterView",
data() {
return {
user: {
username: "",
password: "",
email: "",
phoneNumber: "",
role: "",
},
role : []
};
},computed:{
getRole(){
axios.get('http://localhost:8080/api/role/get').then(res=>{
this.role = res.data;
})
return [];
}
},
methods: {
register() {
axios.post("http://localhost:8080/api/user/register", this.user).then((res) => {
console.log(res.data);
});
},
},
};
</script>
// Error Unexpected asynchronous action in "getRole" computed property vue/no-async-in-computed-properties
I tried async and await , but it seems I got it wrong
Try to run that call inside the created hook :
import axios from 'axios';
export default {
name: "RegisterView",
data() {
return {
user: {
username: "",
password: "",
email: "",
phoneNumber: "",
role: "",
},
role : []
};
},
created(){
this.getRole():
},
methods: {
getRole(){
axios.get('http://localhost:8080/api/role/get').then(res=>{
this.role = res.data;
}).catch(err=>{
this.role = []
})
},
register() {
axios.post("http://localhost:8080/api/user/register", this.user).then((res) => {
console.log(res.data);
});
},
},
};
GetRole uses promises, meaning it doesn't have immediate value but has side-effects, which is considered to be dirty code by the linter (code quality checker)
If you need async computed, use asyncComputed instead, which has immediate value and gets updated of promise resolution automatically
https://github.com/foxbenjaminfox/vue-async-computed for Options API, #vueuse/core for Composition API

Vuex getter method returns undefined

I am trying to call a getter method and it's not getting called for some reason. If I console.log the store I can see that it's undefined:
This is where I'm calling the getter method:
computed: {
client() {
console.log(this.$store); //see above screenshot
console.log(this.$route.params.id); //shows a valid value.
//nothing seems to happen after this point, console.log in the below getter doesn't happen.
return this.$store.getters['clients/clientById', this.$route.params.id];
}
},
here's my getter in clients.js module:
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById(state, id) {
console.log('test'); //this doesn't happen
return state.clients.find(client => client.id === id);
}
}
The first 2 getter methods are working fine, using the same syntax as what I'm doing when I'm calling the clientById getter.
What I'm trying to accomplish is to have an array of client objects, and then when a user clicks on a client in the client list, I grab the ID out of the route params and the appropriate client data is displayed on the page. I'd appreciate any guidance on whether I'm approaching this in the right way as well as I'm new to Vue.
state() {
return {
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
UPDATE:
I'll provide my entire clients.js module in case something is off with that. Everything else seems to be working fine, so not sure if this is related or not. This is an updated version of the getter where I changed it to an arrow function based on your feedback. When I do this, I get another error: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.
I've also tried hard-coding the ID within the getter method and taking it out of the passed-in ID parameter, and that seems to work, but is returning undefined, so it's still not getting a value from state.
import axios from "axios";
export default {
namespaced: true,
state() {
return {
isLoading: false,
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
mutations: {
setLoadingStatus(state, status) {
state.isLoading = status;
},
setClients(state, clients) {
state.clients = clients;
}
},
actions: {
async fetchClients(context) {
context.commit('setLoadingStatus', true);
try {
const resp = await axios.get('http://localhost/api/clients');
context.commit('setLoadingStatus', false);
context.commit('setClients', resp.data);
} catch(e) {
console.log(e);
}
}
},
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById: (state) => (id) => {
return state.clients.find(client => client.id === id);
}
}
};

parse data from firebase in react render

I'd like to parse data I receive from componentdidmount to render.
I have this state:
constructor(props) {
super(props);
this.state = {
loading: true,
data: []
}
}
and this componentdidmount:
componentDidMount() {
var post = [];
var feedRef = firebase.database().ref().child('posts').limitToLast(10);
feedRef.once('value', async (snapshot) => {
post.push(
Object.assign(snapshot.val(), {
key: snapshot.key,
user: snapshot.user,
img: snapshot.img
})
)
this.setState({ data: post, loading: false });
console.log(this.state.data); // has the data
});
}
and this to parse the data:
{this.state.data.map(post => {
return(
<div>
<img src={post.img} />
</div>
)
})}
The problem is, although I have data in state it is not being parse in render. Any ideas what is wrong?
I also have this error: index.js:1 Warning: Each child in a list should have a unique "key" prop.
my data is wrong:
the console.log:
Array(1)
0:
-M7Y4RJMl1pd4ynwXPYJ: {img: "https://", user: "josh", userid: "T87u4DL82IaGO9X"}
-M7Y4RJMl1pdwXPYJ: {img: "https://", user: "josh2", userid: "T87u82IaGO9X"}
-M7Y4RXPYJ: {img: "https://", user: "josh3", userid: "T87u4DL82GO9X"}
-M7Y4RJMl1XPYJ: {img: "https://", user: "josh4", userid: "T87uaGO9X"}
img: undefined
key: "posts"
user: undefined
check the docs https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html
You need to convert the object into an array, the map function in the render is expecting an array, but you are using an object
var obj = snapshot.val();
var arrayPosts = Object.keys(obj).map(function(key) {
return {
key,
user: obj[key].user,
img: obj[key].img
}
});
post = arrayPosts

Vue.js component data not being updated after GET

I have a component that contains a default object, and on create GETs a populated object. When trying to bind this.profile to the new object it seems to get the correct data in the method but the change is not pushed back to other uses of this.profile. Is there a way to force this change to be picked up by the rest of the script?
export default {
data() {
return {
profile: {
firstName: 'Seller First Name',
surname: 'Seller Surname',
username: '',
biography: 'Seller biography.',
phoneNumber: 'Seller Phone Number',
emailAddress: 'Seller Email',
profilePhotoUrl: '',
testimonials: []
}
};
},
components: {
ProfileSummary,
Biography,
TestimonialList,
PaymentsenseCompany
},
created() {
console.log('created');
this.getProfile(this.$route.params.sellerUsername);
},
methods: {
getProfile(sellerUsername) {
axios.get('http://fieldsellerprofileapi.azurewebsites.net/api/fieldseller/' + sellerUsername)
.then(function(response) {
this.profile = Object.assign({}, response.data);
Vue.nextTick(() => {
console.log('after', this);
});
}.bind(this))
.catch(e => {
console.log(e);
// location.replace('/404');
});
}
},
Im not sure, but try this:
getProfile(sellerUsername) {
axios
.get('http://fieldsellerprofileapi.azurewebsites.net/api/fieldseller/' + sellerUsername)
.then(r => this.profile = r.data)
.catch(e => console.log(e))
}
So it turns out the issue wasn't that the values weren't being updated. They were being saved fine, I was just trying to access them in a child component which was not being updated with the parent for some reason. The changes were not propagating down to the children... This may be of use researching if you have the same issue.
Thanks

Categories

Resources