Home > Software design >  Can I use watch from Vue 3 with primitives?
Can I use watch from Vue 3 with primitives?

Time:01-08

Every time I fetch data, I want to change boolean value to render <Loading /> component. I don't want my condition to be dependant on array length. So I decided to do it this way. And <Loading /> component never reacts to state.isLoading change. I tried to test whether this.isLoading changes at all using watch. But watch never logged anything. I've never seen anybody using watch with primitives. The problem is that I don't know if I can use watch with primitives and what I can use instead, like useEffect in React.

App.vue

<script setup>
  import { RouterView } from 'vue-router'
  import { watch, ref, onMounted, reactive } from 'vue';
  import Navbar from './components/Navbar.vue'
  import { useShopStore } from './stores/shopStore';

  const shop = useShopStore()

  const bool = ref(shop.isLoading)

  console.log(bool)

  watch(bool.value, (newBool) => {
    console.log(newBool)
  }, { deep: true })
</script>

Category.vue

<template>
  <LoadingVue v-if="shop.isLoading" />
  <div v-else >
    <CardVue
      v-for="item in shop.category"
      :item="item"
      :key="item.id"
    />
  </div>
</template>

ShopStore.js

actions: {
  async getProducts(path) {
    if (typeof path !== 'string' || path === undefined) return
    this.setLoading()
    try {
      const response = fetch(`https://fakestoreapi.com/products/category/${path}`)
      .then(res => res.json())
      .then(res => this.category = res)
    } catch (error) {
      console.log(error)
      alert('Something went wrong')
    }
    this.setLoading()
  },
  setLoading() {
    console.log('setLoading')
    this.isLoading = !this.isLoading
  }
}

CodePudding user response:

You are creating a new ref over a reactive data. It's like copying by value, the original reactive data and the new ref wrapped over it are not connected. So when shop.isLoading changes, your bool ref doesn't, they are two different variables now.

I guess you are using pinia for the store. If so, the shop.isLoading is already reactive, you don't have to wrap it into a ref.

<Loading v-model="shop.isLoading" />

You can also use storeToRefs helper method from pinia to use destructuring over your store and get refs of your state:

const { isLoading } = storeToRefs(shop)

console.log(isLoading.value)

CodePudding user response:

So. The problem was that I used async but I didn't use await inside the function and that's why condition worked the way it worked. Or didn't work as I expected. Now I fixed it and I want to publicly admit that I am a complete moron. Thank you for your attention. P.S. Still didn't figure out how to use watch. The only way is to watch the whole state object. watch doesn't react to only state.bool value change.

  • Related