Задать вопрос
google_online
@google_online
My morning begins with coffee and Twitter.

Как обновить данные в 'newlevels' computed?

Есть компонент в котором циклом получаю levelы. Каждый levlel имеет свойство favorite(levle.vaforite) либо true или false. В каждом level'e есть иконка

<v-icon :class="{star: x.favorite}" @click='favorite(x)'>star</v-icon>

Функция favorite меняет значение на сервере с true на false. Это работает на сервере, но не обновляется свойство x.favorite в моём `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
}


В компоненте в computed я соединяю levels и userlevels вместе. Оно работает, но по клику на иконку `star` я не могу обновить свойство favorite на true или false(тернарка). Вот мой computed и 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")
  },


И также мой 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>


Нужно как то обновить свойство `favorite` в `newlevels` в computed после клика на иконку.
  • Вопрос задан
  • 101 просмотр
Подписаться 1 Простой Комментировать
Решения вопроса 1
bingo347
@bingo347
Crazy on performance...
Давайте разберемся по-порядку:
1. При клике вызывается favorite(x)
2. favorite диспатчит USERLEVELS_PATCH
3. USERLEVELS_PATCH отправляет запрос на сервер, логирует результат, но ничего не коммитит

Из пункта 3 видим, что стор не мутируется - это 1 проблема

Дальше, какой смысл в геттерах, которые просто оборачивают стейт?
const getters = {
    levels: state => state.levels,
    userlevels: state => state.userlevels
}


Вернемся в компонент, и видим computed newlevels с побочными эффектами... Вы мутируете стейт вне мутации, а вообще в computed (который по факту тот же геттер) не должен мутировать ничего, он должен лишь вычислять значение, которое вернет, например можно сделать так:
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});
      });
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы