0

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?

1 Answer 1

1

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 ...
            }
        }
    },
....

Sign up to request clarification or add additional context in comments.

3 Comments

Ok. one question. If i wan't get access without getters,in the likes-component i do computed property article() {this.$store.state.article;}, and i cant get access to {{article.statistic.likes}}?
and second question - where i can read about this problem? maybe some documentation?
Sorry, I don't understand your question properly, but if you want to read more about the above problem you mentioned, you can check this - vuejs.org/v2/guide/… It's not very clear but this basically says that since Vue doesn’t allow dynamically adding root-level reactive properties, you can either a type for your variable (i.e. for article and article.statistics) or you do a check on your own. PS. Maybe this can help - stackoverflow.com/a/51794374/4868249 It explains how the variables in Vue are evaluated

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.