How to properly use Vuex getters in Nuxt Vue Composition API?

Viewed 3724

I use @nuxtjs/composition-api(0.15.1), but I faced some problems about accessing Vuex getters in computed().

This is my code in composition API:

import { computed, useContext, useFetch, reactive } from '@nuxtjs/composition-api';

  setup() {
    const { store } = useContext();
    const products = computed(() => {
      return store.getters['products/pageProducts'];
    });
    const pagination = computed(() => {
      return store.getters['products/pagination'];
    });

    useFetch(() => {
      if (!process.server) {
        store.dispatch('products/getPage');
      }
    });

    return {
      products,
      pagination,
    };
  }

And the console keeps reporting the warning:

[Vue warn]: Write operation failed: computed value is readonly.

found in

---> <Pages/products/Cat.vue> at pages/products/_cat.vue
       <Nuxt>
         <Layouts/default.vue> at layouts/default.vue
           <Root>

I'm really confused. Because I didn't try to mutate the computed property, just fetching the Data with the AJAX and then simply assign the data to the state in the Vuex mutations.

But I rewrite the code in option API in this way:

export default {
  components: {
    ProductCard,
    Pagination,
  },
  async fetch() {
    if (process.server) {
      await this.$store.dispatch('products/getPage');
    }
  },
  computed: {
    products() {
      return this.$store.getters['products/pageProducts'];
    },
    pagination() {
      return this.$store.getters['products/pagination'];
    },
  },
};

Everything works fine, there's no any errors or warnings. Is it the way I'm wrongly accessing the getters in the composition API or that's just a bug with the @nuxtjs/composition-api plugin?

1 Answers

fix: computed property hydration doesn't work with useFetch #207

This problem might not can be solved until the Nuxt3 come out.

But I found an alternative solution which use the middleware() instead of use useFetch(), if you want to the prevent this bug by fetching AJAX data with Vuex Actions and then retrieve it by Getters via the computed().

I make another clearer example which it's the same context like the question above.

~/pages/index.vue :

<script>
import { computed, onMounted, useContext, useFetch } from '@nuxtjs/composition-api';

export default {
  async middleware({ store }) {
    await store.dispatch('getUser');
  },
  setup() {
    const { store } = useContext();
    const user = computed(() => store.getters.user);

    return {
      user,
    };
  },
}
</script>

~/store/index.js (Vuex)

const state = () => ({
  user: {},
});

const actions = {
  async getUser({ commit }) {
    const { data } = await this.$axios.get('https://randomuser.me/api/');
    console.log(data.results[0]);
    commit('SET_USER', data.results[0]);
  },
};

const mutations = {
  SET_USER(state, user) {
    state.user = user;
  },
};

const getters = {
  user(state) {
    return state.user;
  },
};

If there's something wrong in my answer, please feel free to give your comments.

Related