Sergey S.
Sergey S.

Reputation: 157

vuex. Can't get access to object variable

look at my vuex code:

export default new Vuex.Store({
    state: {
        article: {},
        slug: '',
    },
    actions: {
        getArticleData(context, payload) {
            axios.get('/api/article-json', { params: {slug:payload } }).then((response) =>{
                context.commit('setArticleData', response.data.data);
            });
        }
    },
    getters: {
        articleLikes(state) {
            return state.article.statistic.likes;
        },
        articleViews(state) {
            return state.article.statistic.views;
        }
    },
    mutations: {
        setArticleData(state, payload) {
            state.article = payload;
        },
        setCurrentSlug(state, payload) {
            state.slug = payload;
        },
        setCurrentStatistic(state, payload) {
            state.statistic = payload;
        }
    }
})

the code works like this - getArticleData action set Data in article object. In create() hook set article opbject:

{
"id": 14,
"title": "Deserunt ea natus pariatur sunt eum voluptatem.",
"img": "https://via.placeholder.com/600/5F113B/FFFFFF/?text=LARAVEL:8.*",
"body": "  fugiat.",
"created_at": "1 месяц назад",
"comments": [
    {
        "id": 40,
        "subject": "Impedit inventore quis.",
        "body": "Qui rem ut beatae expedita nemo.",
        "created_at": "2 дня назад"
    },
    {
        "id": 41,
        "subject": "Nam et sit.",
        "body": "Dolor voluptas error eos quod.",
        "created_at": "2 дня назад"
    },
],
"tags": [
    {
        "id": 1,
        "label": "Ut"
    },
    {
        "id": 3,
        "label": "Fugiat"
    },
],
"statistic": 
    {
        "likes": 7,
        "views": 153
    }
}

This object formed by Laravel resource

public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'img' => $this->img,
            'body' => $this->body,
            'created_at' => $this->createdAtForHumans(),
            'comments' => CommentResource::collection($this->whenLoaded('comments')),
            'tags' => TagResource::collection($this->whenLoaded('tags')),
            'statistic' => new StateResource($this->whenLoaded('state')),
        ];
    }

I can't get access to article.statistic.views and article.statistic.likes from getters.

In views component i have code

computed: {
        viewsNumber() {
            return this.$store.getters.articleViews;
        },
    }

and template

<template>
   <span class="badge bg-danger">{{viewsNumber}} <i class="far fa-eye"></i></span>
</template>

this is my console errors

app.js?id=80d6f0783c93a26b57e1:20787 [Vue warn]: Error in render: "TypeError: Cannot read property 'views' of undefined"

found in

---> <ViewsComponent> at resources/js/components/ViewsComponent.vue
       <ArticleComponent> at resources/js/components/ArticleComponent.vue
         <Root>

app.js?id=80d6f0783c93a26b57e1:22054 TypeError: Cannot read property 'views' of undefined

for comments and tags no problems. In comments component i have access to comments^

computed: {
        article() {
            return this.$store.state.article;
        },
    },

<div v-for="comment in article.comments">
    <div class="toast showing" style="min-width: 100%;">
        <div class="toast-body">
            {{comment.body}}
        </div>
     </div>
</div>

What problem with article.statistic.likes and article.statistic.views?

Upvotes: 0

Views: 143

Answers (1)

Vir Gandhi
Vir Gandhi

Reputation: 68

The problem is it cannot verify whether views or likes will be available in articles.statistic. You are not ensuring where articles.statistic will be defined or not.

So the simple solution is do a check before accessing any child element of articles.statistic

e.g. You can redefine your method like -

....

getters: {
        articleLikes(state) {
            if(state.article.statistic){
                return state.article.statistic.likes;
            } else {
                return ...
            }
        },
        articleViews(state) {
            if(state.article.statistic){
                return state.article.statistic.views;
            } else {
                return ...
            }
        }
    },
....

Upvotes: 1

Related Questions