bdemirka
bdemirka

Reputation: 837

Vue.js Typescript I get the data using getter but can't reach it in methods

I am new to Typescript with vuex. I simply want to fetch user list from the backend. Put in the store. I declared custom user type

export interface User {
  id: number;
  firstName: string;
  lastName: string;
  email: string;
}

in my vuex.d.ts file, I declare store module like:

import { Store } from "vuex";
import { User } from "./customTypes/user";

declare module "@vue/runtime-core" {
  interface State {
    loading: boolean;
    users: Array<User>;
  }

  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}

in my store I fetch the users successfully and commit the state:

import { createStore } from "vuex";
import axios from "axios";
import { User, Response } from "./customTypes/user";

export default createStore({
  state: {
    users: [] as User[], // Type Assertion
    loading: false,
  },
  mutations: {
    SET_LOADING(state, status) {
      state.loading = status;
    },
    SET_USERS(state, users) {
      state.users = users;
    },
  },
  actions: {
    async fetchUsers({ commit }) {
      commit("SET_LOADING", true);
      const users: Response = await axios.get(
        "http://localhost:8000/api/get-friends"
      );
      commit("SET_LOADING", false);
      commit("SET_USERS", users.data);
    },
  },

  getters: {
    userList: (state) => {
      return state.users;
    },
    loadingStatus: (state) => {
      return state.loading;
    },
  },
});

I set the getters, I sense that I don't need to set getter for just returning state however this is the only way I could reach the data in my component. Please advise if there is a better way to do it. In my component I accessed the data like:

  <div class="friends">
    <h1 class="header">Friends</h1>
    <loading v-if="loadingStatus" />

    <div v-else>
      <user-card v-for="user in userList" :user="user" :key="user.id" />
      <pagination />
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { mapGetters } from "vuex";
import { User } from "../store/customTypes/user";
=import UserCard from "../components/UserCard.vue";
import Loading from "../components/Loading.vue";
import Pagination from "../components/Pagination.vue";

export default defineComponent({
  name: "Friends",
  components: {
    UserCard,
    Loading,
    Pagination,
  },
  static: {
    visibleUsersPerPageCount: 10,
  },
  data() {
    return {
      users: [] as User[],
      currentPage: 1,
      pageCount: 0,
    };
  },
  computed: {
    ...mapGetters(["loadingStatus", "userList"]),
  },
  mounted() {
    this.$store.dispatch("fetchUsers");
    this.paginate()
  },
  methods: {
    paginate () {
     // this.users = this.$store.state.users
      console.log(this.$store.state.users) 
      console.log(this.userList) 
    }

  }
});
</script>

Now when I get userList with getters, I successfully get the data and display in the template. However When I want to use it in the method, I can't access it when component is mounted. I need to paginate it in the methods. So I guess I need to wait until promise is resolved however I couldn't figure out how. I tried this.$store.dispatch("fetchUsers").then((res) => console.log(res)) didn't work.

What I am doing wrong here?

Upvotes: 0

Views: 1283

Answers (1)

Estus Flask
Estus Flask

Reputation: 222309

An action is supposed to return a promise of undefined, it's incorrectly to use it like this.$store.dispatch("fetchUsers").then(res => ...).

The store needs to be accessed after dispatching an action:

this.$store.dispatch("fetchUsers").then(() => {
  this.paginate();
});

Upvotes: 1

Related Questions