Search code examples
javascriptvue.jsvuejs3pinia

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://i.sstatic.net/Ki6cp.jpg

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://i.sstatic.net/ruNsE.jpg

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://i.sstatic.net/jzXHr.jpg

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?


Solution

  • 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']