Parse JSON to model in React Native getting undefined - react-native

I'm trying to map my JSON Object to a model class like that:
export class Product {
constructor(props) {
this.name = props.Name
this.items = props.Items
this.price = props.Price
this.productID = props.ProductID
this.medias = props.Medias
}
}
But when I get JSON and try to parse to my Model I'm getting the following error
TypeError: undefined is not an object (evaluating 'mostSoldProductsApiResponse.map'
There's my parse code:
const mostSoldProductsApiResponse = await mostSoldProductsApiCall.json().Products;
const arrayProducts = mostSoldProductsApiResponse.map(function(item) {
return new Product(item.Product)
})
If I don't parse the JSON Object to new Product() constructor, the code works fine. But I would like to organize the code. Therefore I would like to implement Product class.

It might be you are using await not on what you expect.
The line await mostSoldProductsApiCall.json().Products is actually first returning a promise, then awaiting on the resulting promise field Products which is undefined because it is not the result of the promise.
something equivalent to:
const promise = mostSoldProductsApiCall.json() // this is the promise
const unresolvedProducts = promise.Products // this is undefined
const mostSoldProductsApiResponse = await unresolvedProducts // this resolves to undefined
Solution
Use parenthesis to await on the actual promise, like so:
const mostSoldProductsApiResponse = (await mostSoldProductsApiCall.json()).Products
Another option:
const mostSoldProductsApiResponse = await mostSoldProductsApiCall.json()
const arrayProducts = mostSoldProductsApiResponse.Products.map(function(item) {
return new Product(item.Product)
})
Hope this helps!

Related

Vue JS composition API can't access array

I am currently trying to learn Vue JS without ever having encountered Javascript.
All the brackets, arrows, etc. are driving me crazy.
With the Composition API, I come across a question that I can't successfully google.
That's working:
setup() {
const store = useStore ();
const packagingdata = ref ([]);
const loadpackagingdata = async () => {
await store.dispatch (Actions.LOADPACKAGING_LIST, 10);
packagingdata.value = store.getters.getPackagingData;
return {
packagingdata,
}
I can access {{packagingdata}}. That contains an array.
{{Packagingdata.products}}
does work
but {{packagingdata.products [0]}} doesn't work.
But when I add it to the setup () like this:
setup() {
const store = useStore ();
const packagingdata = ref ([]);
const getProducts = ref ([]);
const loadpackagingdata = async () => {
await store.dispatch (Actions.LOADPACKAGING_LIST, 10);
packagingdata.value = store.getters.getPackagingData;
getProducts.value = store.getters.getProducts;
};
return {
packagingdata,
getProducts
}
then {{ getProducts }} returns what I wanted even if the getter function only is like this:
get getAddress() {
return this.packagingdata["products"][0];
}
What is happening there?
What am I doing wrong? I would prefer to not create a ref() and getterfunction for every computed value.
Whats the solution with computed?
best regards
I found two methods to avoid the error.
add a v-if="mygetter.length" in the template
check in the getter whether the variable is set and otherwise return false
Both of these prevent an error already occurring when the page is loaded that [0] cannot be found

Nuxt: How to access store in rollbar.js WITHOUT using localStorage?

I am using Nuxt and Rollbar. I have a user id state in store.
My question is, how can I set this user id as a custom payload in the transformer function in rollbar.js WITHOUT using localStorage?
Here is my code:
// plugins/rollbar.js
const transformer = function(payload) {
payload.user_id = user_id_from_store // how to get this from store?
}
// store/index.js
export const state = () => ({
userId: ''
})
export const mutations = {
setUserId(state, userId) {
state.userId = userId
}
}
//components/MyComponent.vue
methods: {
fetch() {
const userId = fetchUserId()
this.$store.commit('setUserId', userId)
}
}
Things I have tried:
In rollbar.js, create and export a function which takes a context object as argument. Then call this function in transformer function to get user_id:
// plugins/rollbar.js
const getUserId = context => {
const user_id = context.store.state.userId
return user_id
}
const transformer = function(payload) {
payload.user_id = getUserId()
}
export default getUserId
When I console.log(context.store)in getUserId function, I got a Store object, but calling the function in transformer function threw Rollbar: Error while calling custom transform() function. Removing custom transform(). TypeError: Cannot read property 'store' of undefined.
At the end, OP succeeded thanks to inject, more info available here: https://nuxtjs.org/docs/2.x/directory-structure/plugins#inject-in-root--context
This one is indeed needed for libraries that are not directly into the Vue ecosystem but that we wish to have working in our Nuxt app.

localstorage returning object on reload

i am using vue.js with vuex
In my vuex action i am calling an external api like this:
//actions.js
getStudent({ commit }) {
new Promise((resolve, reject) => {
student.getStudent()
.then(response => {
localStorage.setItem("userInfo", JSON.stringify(response.data.userData))
commit('UPDATE_USER_INFO', JSON.stringify(response.data.userData), { root: true })
resolve(response)
})
}
}
In this function userdata is set as a localstorage item.
I also call a mutation with commit
when this function is executed for the first time everything works fine with for example this code:
//state.js
const userInfoLocalStorage = JSON.parse(localStorage.getItem("userInfo"))
const setUserRole = () => {
const userRole = userInfoLocalStorage ? userInfoLocalStorage.role : 'student'
return userRole
}
const state = {
Role: setUserRole()
}
Now whenever i reload the page JSON.parse returns the error Unexpected token o in JSON at position 1 and when i remove JSON.parse it returns [object Object]. But when i use JSON.stringify it returns a json object but this works only on first load.
I find it very confusing
Please help me clear out what i should use for best practice.
The problem is on this line:
const userRole = userInfoLocalStorage ? JSON.parse(userInfoLocalStorage).role : 'student'
You're calling JSON.parse on an object (userInfoLocalStorage) that has already been deserialized with JSON.parse on the line above:
const userInfoLocalStorage = JSON.parse(localStorage.getItem("userInfo"))
Instead, just do const userRole = userInfoLocalStorage ? userInfoLocalStorage.role : 'student'

Cannot add/remove sealed array elements

I am combining a graphql api call with an array modification.
async deletePhoto(photoId, driveId, index) {
this.property.photos.splice(index, 1);
await api.photos.remove(this.property.id, photoId, driveId);
},
api call:
const remove = async (propertyId, photoId, driveId) => {
const mutation = gql`
mutation photoDelete($propertyId: Int!, $photoId: String!, $driveId: String!) {
deletePropertyPhoto(propertyId: $propertyId, photoId: $photoId, driveId: $driveId)
}
`;
const result = await apolloClient.mutate({
mutation,
variables: {
propertyId,
photoId,
driveId,
},
});
console.log(result);
return result;
};
Problem:
Uncaught (in promise) TypeError: Cannot add/remove sealed array elements
at Array.splice (<anonymous>)
at VueComponent._callee3$ (http://localhost:3030/_nuxt/3.js:284:38)
at tryCatch (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:26549:40)
at Generator.invoke [as _invoke] (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:26787:22)
at Generator.prototype.(anonymous function) [as next] (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:26601:21)
at step (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8714:30)
at http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8732:14
at Promise (<anonymous>)
at F (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8036:28)
at VueComponent.<anonymous> (http://localhost:3030/_nuxt/vendor.bundle.5559a1f55cb4b1323e8d.js:8711:12)
What makes this error so weird? When I remove the api call, it works fine. This doesn't make any sense to me, because the api call has nothing to do with the array modification.
EDIT:
This is insane, sometimes the error appears, and sometimes the splicing works just fine. This is the most random bug I've ever encountered.
EDIT2:
When fetching the properties (and photos) I've already made an object copy of the graphql result:
async asyncData({ params }) {
const fetchedProperty = await api.properties.findOne(params.id);
return {
oldProperty: fetchedProperty,
property: Object.assign({}, fetchedProperty),
};
},
Your API call is apparently returning an object (fetchedProperty) with a photos array that has been sealed via Object.seal.
You are setting your property data property to Object.assign({}, fetchedProperty), which is assigning the value of each property in fetchedProperty to an empty array.
This still means that the value of photos (which is a sealed array) is getting set to the empty object being assigned to your property data property.
You need to explicitly copy the values of the photos array and set that to the photos property of the data property. Maybe something like this:
async asyncData({ params }) {
const fetchedProperty = await api.properties.findOne(params.id);
let property = Object.assign({}, fetchedProperty);
let property.photos = [...fetchedProperty.photos];
return {
oldProperty: fetchedProperty,
property: property
};
}
Another way to delete a sealed Object is using slice is
this.property.photos = this.property.photos.slice(0, idx).concat(this.property.photos.slice(idx + 1));
In your function as:
async deletePhoto(photoId, driveId, index) {
this.property.photos = this.property.photos.slice(0, idx).concat(this.property.photos.slice(idx + 1));
await api.photos.remove(this.property.id, photoId, driveId);
},

react-native fetch undefined on button press

I have a function when I press a button to get data
however my app is erroring on fetch undefined
async doNext() {
const response = await fetch(`https://facebook.github.io/react-native/movies.json`);
const jsonData = await response.json();
console.log(jsonData);
}
error:
Possible Unhandled Promise Rejection (id: 0)
undefined is not a function evaluating 'fetch'('https://facebook.github.io/react-native/movies.json'))
I also tried to write it like this:
doTest = async () => {
const response = await fetch(`https://facebook.github.io/react-native/movies.json`);
const jsonData = await response.json();
console.log(jsonData);
}
doNext() {
this.doTest();
}
but got the same error
how do I make 'fetch' defined, if I console.log(fetch) I get undefined
found the problem in my code
self = this;
missing let or var, this was in index.android.js this line alone broke everything no warnings appeared for this