Search code examples
javascriptvue.jssearchnuxt.jsvuex

How to visualize the initial array when search input by title is empty again?


After searching in the input field a todo item by title, and than making the search input empty I'm expecting to get rendered the initial array of todos once again. I tryed to achieve it with if statement but it doesn't work and only the searched before todo item is only rendered, not the initial list of todos. I'm not sure that the if statement is the best approach.

https://stackblitz.com/edit/nuxt-bootstrap-vue-dynamic-img-bkwixg?file=pages%2Findex.vue,store%2Findex.js,components%2FTask.vue

// Child component

<template>
      <input
        type="text"
        v-model="search"
        @keypress.enter="searchTask"
        placeholder="search task"
      />
      <button @click="searchTask" class="btn">Search</button>
      <Task v-for="task in tasks" :key="task.id" :task="task" />
</template>

<script>
export default {
  computed: {
    tasks() {
      return this.$store.getters.getTasks;
    },
  },
  mounted() {
    this.$store.dispatch('getTasks').then((data) => console.log(this.tasks));
  },
  methods: {
    searchTask() {
      let search = this.search;
      this.$store.commit('searchTask', search);
    },
  },
};
</script>

// Store 

export const state = () => ({
  tasks: [],
});

export const actions = {
  async getTasks(context) {
    const res = await fetch('https://dummyjson.com/todos/user/5');
    if (res.ok) {
      let result = await res.json();
      context.commit('setTasks', result.todos);
    }
    return res.ok;
  },

export const mutations = {
  setTasks(state, data) {
    state.tasks = data;
  },
  searchTask(state, search) {
    if (search) {
      state.tasks = state.tasks.filter((t) => {
        return t.todo.toLowerCase().includes(search.toLowerCase());
      });
    } else if (search === '') {
      return state.tasks;
    }
  },
};

export const getters = {
  getTasks(state) {
    return state.tasks;
  },
};


Solution

  • You shouldn't mutate the original state, instead, you can define a getter with method style access :

    export const state = () => ({
      tasks: [],
    });
    
    export const actions = {
      async getTasks(context) {
        const res = await fetch('https://dummyjson.com/todos/user/5');
        if (res.ok) {
          let result = await res.json();
          context.commit('setTasks', result.todos);
        }
        return res.ok;
      },
    
    export const mutations = {
      setTasks(state, data) {
        state.tasks = data;
      },
    };
    
    export const getters = {
      getTasks:(state) => (search) => {
       if (search) {
          return state.tasks.filter((t) => {
            return t.todo.toLowerCase().includes(search.toLowerCase());
          });
        } else if (search === '') {
          return state.tasks;
        }
      }
    };
    

    You should call it like :

    computed: {
        tasks() {
          return this.$store.getters.getTasks(this.search);
        },
      },