Keep getting [Object Object] in hybrid app Javascript - javascript

I'm building a hybrid app using Nuxt JS, Cordova and Cordova Native Storage (essentially localstorage).
I'm saving an object to native storage, and retrieving it on page load within mounted() however, I keep getting the following error no matter what I try to access the object data:
[Object Object]
My JS in the component which is loaded on every page is:
import { mapState } from 'vuex';
export default {
mounted () {
document.addEventListener("deviceready", this.getNativeStorage(), false)
},
methods: {
getNativeStorage() {
window.NativeStorage.getItem("beacon_native_storage", (value) => {
var parseObj = JSON.parse(value)
alert(parseObj)
alert(parseObj.localStorage)
}, (error) => {
alert(`Error: ${error.code}-${error.exception}`)
});
},
refreshNativeStorage(currentState) {
window.NativeStorage.initWithSuiteName("beacon");
window.NativeStorage.setItem("beacon_native_storage", JSON.stringify(currentState), () => {
alert('Stored currentState')
}, (error) => {
alert(`Error: ${error.code}`)
});
}
},
computed: {
state () {
return this.$store.state
}
},
watch: {
state: {
handler: function (val, Oldval) {
setTimeout(function () {
this.refreshNativeStorage(this.state)
}.bind(this), 10)
},
deep: true
}
}
}
And the object from Vuex looks like:
export const state = () => ({
pageTitle: 'App name',
dataUrls: [],
intervalData: [],
settings: [],
experimentalFeatures: [],
customAlertSeen: false,
user: null,
account: null,
payloadOutput: null
})
Every time the getItem runs, alert(parseObj) always returns [Object Object] rather than for instance, the data. And if I try returningparseObj.localStorage.pageTitlewhich is clearly defined instore/localStorage.jsit returnsundefined`
Where am I going wrong here?

So, what happens, is that localStorage stores STRINGS, not objects.
When you save your item to localStorage, first convert it to a string, then parse it from a string when you retrieve it.
localStorage.setItem('a', {b:'c',d:'e'})
localStorage.getItem('a') // "[object Object]" <- note the quotes!
localStorage.setItem('a', JSON.stringify({b:'c',d:'e'}))
JSON.parse(localStorage.getItem('a')) // {b: "c", d: "e"}

Related

Pinia|Vue3 I can't access the property of the object that returned from the Pinia action

first of all I am using the Mockjs to simulate the backend data:
{
url: "/mockApi/system",
method: "get",
timeout: 500,
statusCode: 200,
response: { //
status: 200,
message: 'ok',
data: {
'onlineStatus|3': [{
'statusId': '#integer(1,3)',
'onlineStatusText': '#ctitle(3)',
'onlineStatusIcon': Random.image('20*20'),
'createTime': '#datetime'
}],
'websiteInfo': [{
'id|+1': 1,
}]
}
}
}
the data structure would be: https://imgur.com/a/7FqvVTK
and I retrieve this mock data in Pinia store:
import axios from "axios"
import { defineStore } from "pinia"
export const useSystem = defineStore('System', {
state: () => {
return {
systemConfig: {
onlineStatus: [],
},
}
},
actions: {
getSystemConfig() {
const axiosInstance = axios.interceptors.request.use(function (config) {
// Do something before request is sent
config.baseURL = '/mockApi'
return config
}, function (error) {
// Do something with request error
return Promise.reject(error);
})
axios.get('/system/').then(res => {
this.systemConfig.onlineStatus = res.data.data.onlineStatus
})
// console.log(res.data.data.onlineStatus)
axios.interceptors.request.eject(axiosInstance)
}
}
})
I use this store in the parent component Profile.vue:
export default {
setup() {
const systemConfigStore = useSystem()
systemConfigStore.getSystemConfig()
const { systemConfig } = storeToRefs(systemConfigStore)
return {
systemConfig,
}
},
computed: {
getUserOnlineStatusIndex() {
return this.userData.onlineStatus//this would be 1-3 int.
},
getUserOnlineStatus() {
return this.systemConfig.onlineStatus
},
showUserOnlineStatusText() {
return this.getUserOnlineStatus[this.getUserOnlineStatusIndex - 1]
},
},
components: {UserOnlineStatus }
}
template in Profile.vue I import the child component userOnlineStatus.vue
<UserOnlineStatus :userCurrentOnlineStatus="userData.onlineStatus">
{{ showUserOnlineStatusText }}
</UserOnlineStatus>
here is what I have got https://imgur.com/fq33uL8
but I only want to get the onlineStatusText property of the returned object, so I change the computed code in the parent component Profile.vue:
export default {
setup() {
const systemConfigStore = useSystem()
systemConfigStore.getSystemConfig()
const { systemConfig } = storeToRefs(systemConfigStore)
return {
systemConfig,
}
},
computed: {
getUserOnlineStatusIndex() {
return this.userData.onlineStatus//this would be 1-3 int.
},
getUserOnlineStatus() {
return this.systemConfig.onlineStatus
},
showUserOnlineStatusText() {
return this.getUserOnlineStatus[this.getUserOnlineStatusIndex - 1]['onlineStatusText']//👀I chage it here!
},
},
components: {UserOnlineStatus }
}
but I will get the error in the console and it doesn't work:
https://imgur.com/Gb68Slk
what should I do if I just want to display the specific propery of the retrived data?
I am out of my wits...
I have tried move the store function to the child components, but get the same result.
and I google this issue for two days, nothing found.
Maybe it's because of I was trying to read the value that the Profile.vue hasn't retrieved yet?
in this case, how could I make sure that I have got all the value ready before the page rendered in vue3? Or can I watch this specific property changed, then go on rendering the page?
every UX that has data is coming from remote source (async data) should has spinner or skeleton.
you can use the optional chaining for safe access (if no time to await):
return this.getUserOnlineStatus?.[this.getUserOnlineStatusIndex - 1]?.['onlineStatusText']

Vue: lost object attribute after put response.data to local aray

I have API that returns json objects like this:
[
{"id":3,"delivery_from":"bsl","task_id":410169,"unit_job_id":224128,"completed_at":null,"deleted_at":null,"created_at":"2021-10-20T13:24:07.000000Z"},
{"id":3,"delivery_from":"bsl","task_id":410169,"unit_job_id":224128,"completed_at":null,"deleted_at":null,"created_at":"2021-10-20T13:24:07.000000Z"}
]
When i print response.data in browser console, I see that all objects params are ok, but when I put response.data to local array deliveryJobs: [], then I see that task_id attribute is undefined. What wrong I am doing?
<script>
import AxiosHandler from './mixins/AxiosHandler'
import axios from 'axios'
export default {
i18n: window.i18n,
mixins: [
AxiosHandler,
],
props: {
unitJobId: Number,
unitId: Number,
taskId: Number
},
data: () => ({
deliveryJobs: [],
unitJob: {}
}),
async created () {
this.getDeliveryJobs()
},
methods: {
getDeliveryJobs () {
axios
.get(`/api/v1/unitjobdelivery`, { params : { unit_job_id : this.unitJobId } })
.then(response => {
this.deliveryJobs = response.data
})
.catch(this.handleAxiosError)
}
}
}
</script>
Solution found.
My API was returning laravel collection instead of array. I changed return to array and now all works fine.

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);
}
}
};

unexpected side effect vue

I am a newbie in vue.js. I have a problem with side effect in computed property. I'm not sure why i'm getting an unexpected side effect in computer property error with the code below. ESlint shows me this error in console. I found what does it mean, but I dont have any idea how to change. Any ideas?
export default {
name: "Repaid",
components: {
VueSlideBar
},
data() {
return {
response: {},
slider: {
lineHeight: 8,
value: 2000,
data: []
},
days: {},
monthCounts: [5],
currentMonthCount: 5,
isLoading: false,
errorMessage: "",
validationError: ""
};
},
computed: {
finalPrice() {
const index = this.monthCounts.indexOf(this.currentMonthCount);
this.days = Object.keys(this.response.prices)[index]; =>this is my side effect
const payment = this.response.prices[this.days]
[this.slider.value].schedule[0].amount;
}
},
I read that i should add slide() to my variable that.days, to mutate the original object. Or maybe I should carry them to the methodes.
EDIT
I carried all my calculations to methods and trigger a function in computed property.
Now it looks like this:
methods: {
showPeriod() {
const index = this.monthCounts.indexOf(this.currentMonthCount);
this.days = Object.keys(this.response.prices)[index];
const payment = this.response.prices[this.days][this.slider.value]
.schedule[0].amount;
return "R$ " + payment;
},
}
computed: {
finalPrice() {
if (!this.response.prices || this.monthCounts === []) {
return "";
}
return this.showPeriod();
}
},
It's coming from "eslint-plugin-vue" and the link for that rule is below,
https://eslint.vuejs.org/rules/no-side-effects-in-computed-properties.html
Either you override this rule in your eslint rules file or you can simply turn off the eslint for this specific line like below
this.days = Object.keys(this.response.prices)[index]; // eslint-disable-line
--
One more thing (Not related to your question) is that you need to return some value in computed.

Vue data not getting overwritten by a eventHub call

I cant figure out, why my variable inside data() isnt getting overwritten.
Code looks like this:
export default {
props: ["store", "link", "index", "isStoreOpen"],
data() {
return {
hovered_over_icon: false,
window_width: window.innerWidth,
opened: null
}
},
methods: {
toggleRestaurantView() {
this.link()
},
check_for_breaks(text){
return text.replace(/\*break\*/g, '<br/>');
},
change_state(state){
this.opened = state
}
},
computed: {
url() {
return ((this.store) ? `https://www.google.com/maps/dir/Current+Location/${this.store.address.location.lat},${this.store.address.location.lon}` : '#')
},
isOpen() {
return this.store.openNow;
}
},
created(){
eventHub.$on('restaurantOpened', (state) => this.change_state(state));
eventHub.$on('changeFilteredRestaurantsAfterRestaurantVisit', (state) => this.store = state);
}
}
</script>
But when I log the this.opened after reassigning new value, I get the correct one, however when I check Vue console, it stayed on null.
Even if I do this.$forceUpdate() it doesnt get updated.
Never happened this to me in my Vue career so far, a bit confused.

Categories

Resources