0

When I change body.title in v-text-field I see success requests in network tab and response with new data but there is no changed data on the page.

otherwise, if I use const { data: _data }: any = await useFetch('/api/rooms ... function just inside "async setup() {" of vue file i see new data on the browser page.

Help please, why useFetch doesnt return data from pinia to vue file.

P.S in pinia store i see changed data only within the useFetch(....,onResponse({ response }) { // new data here by body param, but return response._data doesnt return data outside of this one

I have store function:

export const useRoomStore = defineStore('roomStore', () => {
  const body = ref<IRoomBody>(ROOM_BODY_DEFAULT)
  const data = ref<any>([])

  const fetch = async () => {

    const { data: _data }: any = await useFetch('/api/rooms', {
      key: 'rooms',
      method: 'post',
      body,
      onRequest({ options }) {
        let bearer = 'Bearer '
        const token = localStorage.getItem('access_token')

        if (!token) {
          console.log('token ERROR GO TO LOGIN', token)
        } else {
          bearer = bearer + token
        }

        const headers = new Headers(options.headers)
        headers.set('Content-Type', 'application/json')
        headers.set('Authorization', bearer)

        options.headers = headers
      },
    })

    data.value = _data.value
  }


  return {
    body,
    data,

    fetch
  }
}

Also vue:

<template>
  <v-card class="pa-5 my-5">
    <v-card-title class="pa-0">Filter</v-card-title>

    <v-card-text class="my-5">
      <v-row>
        <v-col>
          <v-text-field v-model="body.title" append-inner-icon="mdi-close" label="Name" variant="solo" />
        </v-col>
      </v-row>
    </v-card-text>
  </v-card>

  <v-card class="pa-5 my-5">
    <v-card-title class="pa-0">List</v-card-title>

    <v-card-text class="my-5">
      <v-row v-for="item in data" :key="item.id">
        <v-col>ID: {{ item.id }}</v-col>
        <v-col>TITLE: {{ item.title }}</v-col>
      </v-row>
    </v-card-text>
  </v-card>
</template>

<script lang="ts">
import { useRoomStore } from '@/stores/RoomStore'

export default defineComponent({
  async setup() {
    const roomStore = useRoomStore()

    const { fetch } = roomStore
    const { data, body } = storeToRefs(roomStore)

    onMounted(async () => {
      fetch()
    })

    return {
      body,
      data,
    }
  },
})
</script>

My attempt to use $fetch instead useFetch:

const fetch = async () => {
    const res = $fetch(`/api/rooms`, {
      method: 'post',
      body: body.value,
      onRequest({ options }) { ... same rest

//useAsyncData('rooms', () => fetch()) // tried too
  onMounted(async () => {
    await fetch()
  }

in this case even no requests in tab network by body.title changing.

looks like $fetch doesnt watch body params

5
  • useFetch isn't a glorified fetch. It's generally a mistake to use a composable anywhere but setup body, any other usage depends on its implementation. You can use $fetch for this purpose Commented Jun 9 at 15:06
  • @EstusFlask, i tried but $fetch doesnt watch body params. I updated this post Commented Jun 9 at 15:45
  • 2
    It's unclear what's the goal of useRoomStore's fetch. Basically you either call useFetch in the body of useRoomStore and you don't need your own fetch function. Or you use $fetch and call it when you need it to fetch data, e.g. in a watcher if you need this on body change Commented Jun 9 at 15:57
  • oh it worked! I Just used useFetch in the body of useRoomStore X_X. then it is impossible to reach same result from store function like my fetch() action Commented Jun 9 at 16:07
  • 1
    This differs from the original attempt because it will behave similarly on server and client side. If the intention of fetch inside onMounted is to prevent this on server side, you can do this with immediate:false option and by using useFetch's refresh() Commented Jun 9 at 16:53

1 Answer 1

0

Just a small suggestion. Would you like to try writing it like this? It might help.

export const useRoomStore = defineStore('roomStore', () => {
  const body = ref<IRoomBody>(ROOM_BODY_DEFAULT)

  const { data, execute } = useFetch('/api/rooms', {
    key: 'rooms',
    method: 'post',
    body,
    immediate: false,
    onRequest ({ options }) {
      let bearer = 'Bearer '
      const token = localStorage.getItem('access_token')

      if (!token) {
        console.log('token ERROR GO TO LOGIN', token)
      } else {
        bearer = bearer + token
      }

      const headers = new Headers(options.headers)
      headers.set('Content-Type', 'application/json')
      headers.set('Authorization', bearer)

      options.headers = headers
    },
  })

  const fetch = () => execute()

  return {
    body,
    data,
    fetch,
  }
})

And if you’re interested in learning more about how to use $fetch, useFetch, and useAsyncData, this video might be helpful.

https://www.youtube.com/watch?v=njsGVmcWviY

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.