Vuex getter для фильтра не обновляется после изменения состояния массива - PullRequest
0 голосов
/ 22 января 2020

Я создаю приложение todo. Есть кнопка для переключения проверенного / завершенного состояния всех задач. Я изменяю массив state, но getters не обновляется. Когда я нажимаю кнопку toggle complete, база данных и массив state.todos обновляются, но $store.getters.filteredTodos не обновляется.

Поэтому некоторые задачи отображаются некорректно (некоторые проверяются, а другие - нет, когда все должен быть отмечен или не отмечен)

    // in getters
    filteredTodos(state) {
        if (state.filter == 'active') {
            return state.todos.filter(todo => !todo.completed);
        }

        if (state.filter == 'completed') {
            return state.todos.filter(todo => todo.completed);
        }

        return state.todos;
    },

    // in mutations
    retrieveTodos(state, todos) {
        Vue.set(state, 'todos', todos);

        // tried the following, but also didn't work
        //state.todos.splice(0, state.todos.length, ...todos);
    },

    // in actions
    toggleCompleted(context, completed) {
        axios.patch('/todos/toggle-completed', {completed})
            // response.data is the array of the updated todo items
            .then(response => context.commit('retrieveTodos', response.data))
            .catch(e => console.log(e));
    },

Из нескольких сообщений здесь, в StackOverflow и в VueForum, я видел одно и то же решение:

        Vue.set(state, 'todos', todos);
        // or
        state.todos.splice(0, state.todos.length, ...todos);

Ни одно из них не сработало. $store.state обновляется, но $store.getters.filteredTodos нет.

Как решить эту проблему?

ОБНОВЛЕНИЕ

Я подписан этот урок на YouTube , чтобы начать работу с Vue, но я кое-что делаю самостоятельно. В этом уроке парень создает проект Vue для fronend и проект Laravel для backend. Я сделал то же самое.

1 Ответ

0 голосов
/ 22 января 2020

Я обнаружил, что проблема не имеет ничего общего с getters или state. Оба обновлялись корректно тремя способами, которые я пробовал.

Проблема была в компоненте Todo. Ранее код был примерно таким:

// in the template 
        <label class="todo-action" :for="`todo-checked-${id}`">
            <input type="checkbox" v-model="completed" 
                   :id="`todo-checked-${id}`" @change="update">
        </label>

        <div class="todo-title">
            {{title}}
        </div>

// inside script tag
    data() {
        // this allow me to access this.id, this.completed, and this.title 
        // instead of this.todo.id, this.todo.completed, and this.todo.title
        return this.todo;
    },

Проблема в том, что data не обновлялся. Я исправил это следующим образом

// in the template I access the props from the todo item, so it is always up to date
        <label class="todo-action" :for="`todo-checked-${todo.id}`">
            <input type="checkbox" v-model="todo.completed" 
                   :id="`todo-checked-${todo.id}`" @change="update">
        </label>

        <div class="todo-title">
            {{todo.title}}
        </div>

Да, это было очень простое решение

...