M
M
Mike2019-10-30 20:12:15
Vue.js
Mike, 2019-10-30 20:12:15

How to update data in 'newlevels' computed?

There is a component in which I get levels in a cycle. Each levlel has a favorite(levle.vaforite) property that is either true or false. Each level has a
`star` icon. The favorite function changes the value on the server from true to false. This works on the server, but does not update the x.favorite property in my `newlevels` computed.

import axios from 'axios'

const state = {
    level: {},
    levels: [],
    question: {},
    questions: [],
    userlevels: []
}

const actions = {
    // это я получаю когда логинюсь в моё app, к этому притензий нет 
    LEVELS: ({commit}) => {
        axios.get('/ef/levels/')
        .then(response => {
            commit('LEVELS', response.data)
        })
        .catch(error => {
            console.log(error, 'something went wront')
        })
    },
    //  это я диспатчу в компоненте
    USERLEVELS: ({commit}) => {
        axios.get('/ef/userlevel/')
        .then(response => {
            console.log('I am from USERLEVELS', response.data)
            commit('USERLEVELS', response.data)
        })
        .catch(error => {
            console.log(error, 'something went wrong')
        })
    },
    // сдесь я отправляю на сервер true или false
    // оно меняется на сервере, но не меняется в vue.js
    USERLEVELS_PATCH: ({commit}, payload) => {
        axios.patch('/ef/userlevel/' + payload.id + '/', payload.data)
        .then(response => {
            console.log('I am from USERLEVELS_PATCH', response.data)
        })
    }
}

const mutations = {
    LEVELS: (state, data) => {
        state.levels = data
    },
    USERLEVELS: (state, data) => {
        state.userlevels = data
    },
}

const getters = {
    levels: state => state.levels,
    userlevels: state => state.userlevels
}

export default {
    namespaced: true,
    state,
    actions,
    mutations,
    getters
}

In the computed component, I connect levels and userlevels together. It works, but when I click on the `star` icon, I can't update the favorite property to true or false (ternark). Here is my computed and methods:
computed: {
    ...mapGetters('ef', ["levels", "userlevels"]),
    newlevels: function () {
      this.levels.forEach(a => {
        this.userlevels.forEach(b => {
          if (a.id === b.level) {
            a['favorite'] = b.favorite
            a['complete'] = b.complete
            a['progress'] = b.progress
            a['userlevel_id'] = b.id
          } else {
            a['favorite'] = a.favorite || false
            a['complete'] = b.complete
            a['progress'] = b.progress || 0;
          }
        })
      })
      return this.levels
    }
  },
  methods: {
      favorite(level) {
        let id = level.id
        let data = {favorite: !level.favorite}
        this.$store.dispatch('ef/USERLEVELS_PATCH', {id, data})
    },
    created() {
        this.$store.dispatch("ef/USERLEVELS")
  },

And also my templete
<v-flex v-for="x in newlevels'" :key="x.id">
            <v-card>
              <v-card-title>
                <router-link :to="{ name: 'questions', params: {id: x.id} }">{{ x.level }}</router-link>
                <v-spacer></v-spacer>
                <v-icon :class="{star: x.favorite}" @click="favorite(x)">star</v-icon>
                {{ x }}
              </v-card-title>
            </v-card>
        </v-flex>

You need to somehow update the `favorite` property in `newlevels` in computed after clicking on the icon.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Belyaev, 2019-10-31
@google_online

Let's sort it out in order:
1. When clicked, favorite(x) is called
2. favorite dispatches USERLEVELS_PATCH
3. USERLEVELS_PATCH sends a request to the server, logs the result, but does not commit anything
From point 3, we see that the store does not mutate - this is 1 problem
Further, what's the point in getters that just wrap the state?

const getters = {
    levels: state => state.levels,
    userlevels: state => state.userlevels
}

Let's go back to the component and see computed newlevels with side effects... You mutate the state outside of the mutation, but in general nothing should be mutated in computed (which is in fact the same getter), it should only calculate the value that it will return, for example, you can do this :
newlevels: function () {
      return this.levels.map(level => {
        return this.userlevels.reduce((acc, userlevel) => {
          // если честно, меня еще дико смущает, что происходит тут... но автору виднее
          if (level.id === userlevel.level) {
            acc['favorite'] = userlevel.favorite
            acc['complete'] = userlevel.complete
            acc['progress'] = userlevel.progress
            acc['userlevel_id'] = userlevel.id
          } else {
            acc['favorite'] = acc.favorite || false
            acc['complete'] = userlevel.complete
            acc['progress'] = userlevel.progress || 0;
          }
          return acc;
        }, {...level});
      });
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question