Search code examples
javascriptvue.jsvuejs2vuex

Could not load UI with data during async action from localstorage


When I click on a certain "task", it loads correctly, and displays the correct UI with data. The error occurs precisely when clicking on the link through the browser input window - localhost:port/task/edit/id, or when I manually refresh the page of each "task". How can I resolve this issue?

router.js:

{
            path: '/task/edit/:id',
            name: 'edit-task',
            component: EditView,
},

Sample of code, with EditView:

<template>
  <div>
    <task-edit :task="task" v-if="task" :key="taskId"/>
    <p v-else>Loading task...</p>
  </div>
</template>

<script>

export default {
  name: 'EditView',
  components: {
    TaskEdit,
  },
  computed: {
    ...mapState(['tasks']),
    taskId() {
      return this.$route.params.id;
    },
    task() {
      return this.tasks.find((task) => task.id === this.taskId);
    },
  },
  async created() {
    await this.$store.dispatch('retrieveTaskById');
  },
};
</script>

store.js with actions for loading tasks:

...
  retrieveTaskById({ state }, taskId) {
        console.log('Loading task from localStorage...');
        state.tasks.find(task => {
            console.log(task.id, 'Task loaded')
            return task.id === taskId
        });
    },
...

Here is the output of console.logs when i manually navigate to the "edit" page:

Loading tasks from localStorage...

Here is the output when I navigate from "home" page:

Loading task from localStorage... 1 'Task loaded'


Solution

  • The only proble I could figure out in your code snippet is that you weren't passing the taskId to the action 'retrieveTaskById'. However I fixed it and made some improvements.

    // State
    retrievedTaskById: {}
    
    // Mutation
    setRetrievedTaskById({ state }, payload) {
        state.retrievedTaskById = payload
    }
    
    // Action
    retrieveTaskById({ commit }, taskId) {
        const task = state.tasks.find(task => task.id === taskId);
        commit('setRetrievedTaskById', task)
    }
    
    // Getter
    retrievedTaskById({ state }) {
        return state.retrievedTaskById
    }
    

    <template>
      <div>
        <task-edit :task="task" v-if="task" :key="taskId"/>
        <p v-else>Loading task...</p>
      </div>
    </template>
    
    <script>
    export default {
      name: 'EditView',
      components: {
        TaskEdit,
      },
      computed: {
        taskId() {
          return this.$route.params.id
        },
        task() {
          return this.$store.getters.retrievedTaskById
        }
        // Same: ...mapGetters(['retrievedTaskById']),
      },
      created() {
        this.$store.dispatch('retrieveTaskById', this.taskId)
      }
    };
    </script>