Nuxt 3 dynamic page changes URL but content remains the same and data is only fetched once
P粉476883986
P粉476883986 2023-11-03 14:39:04
0
1
659

I have a products/index page with products/[slug] in the main product page and I have a NuxtLink to change the page and go to products/[slug] and get the data for that product.

On the first click, I have the correct data, but when I click back or click on the product/index page and then try to click on another product, I have the first product I clicked on and the information for each product, Again I got the information for the first product I clicked on.

Using console.log allowed me to find that my fetched data has not changed, am I missing something here?

Using :key and :page-key on does not work.

The first product I clicked

The second product is still unchanged, the data comes from the first product

The third picture is still unchanged

productComponent.vue

<template>
  <div class="mx-auto rounded border mb-7 border-blue-200 pt-1 px-2 mx-1 mb-2">
    <NuxtLink :to="link">
      <img
        class="rounded mx-auto mb-3 border-b border-y-blue-300 pb-3"
        :src="img"
        :alt="alt"
      />
      <div class="mt-2">
        <div>
          <div class="items-center font-bold text-slate-700 leading-snug">
            <p class="pr-3">{{ title }}</p>
          </div>
          <div class="mt-2 text-lg text-slate-600 pr-3 pb-2">
            قیمت : {{ price }} تومان
          </div>
        </div>
      </div>
    </NuxtLink>
  </div>
</template>

<script>
export default {
  name: 'ProductComponent',
  props: ['title', 'price', 'img', 'alt', 'link'],
}
</script>

products/index.vuePage

<script setup>
useHead({
  title: 'محصولات',
})
const {data, pending, refresh, error} = await useFetch('http://127.0.0.1:8000/api/products')
const products=data._value.data.data
</script>
<template>
  <div>
    <main  class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
      <div class="relative z-10 flex items-baseline justify-between pt-24 pb-6 border-b mb-7 border-gray-200">
        <h1 class="text-4xl font-extrabold tracking-tight ">محصولات</h1>
      </div>
      <div class=" border border-blue-300 mx-auto p-4 mb-7">
        <div class="grid sm:grid-cols-2 md:grid-cols-2 gap-2 lg:grid-cols-3 xl:grid-cols-4">
          <div v-for="(product,index) in products" :key="index">
            <product-component :title="product.name"
                               :price="product.price"
                               :img="'http://127.0.0.1:8000/'+product.image[0].indexArray.large"
                               :alt="product.name"
                               :link="'/products/'+product.slug">
            </product-component>
          </div>
        </div>
      </div>
    </main>
  </div>
</template>

product/[slug]

<script setup>
const route = useRoute();
const {data: productData, pending, refresh, error} = await useFetch(`http://127.0.0.1:8000/api/products/${route.params.slug}`)
const product = productData._value.data[0]
console.log(product)
</script>
<template>
  <div class="container mx-auto">
    <section class="grid grid-cols-12 gap-3 mb-7 ">
      <!--      little pic-->
      <div class="md:col-span-1 mx-auto md:flex md:flex-wrap hidden overflow-auto" style="max-height: 36rem">
        <div class="cursor-pointer bg-amber-100 max-h-9">
          <div class="max-h-fit mb-3 " v-for="(myImage , index) in product.image" :key="index"
               @click="switchImage('http://127.0.0.1:8000/'+myImage.indexArray.large)">
            <img class="object-fill " style="width: 80px;height: 60px"
                 :src="'http://127.0.0.1:8000/'+myImage.indexArray.large"
                 :alt="myImage.alt">
          </div>
        </div>
      </div>
      <!--      end of little pic-->
      <!--      pic-->
      <div v-if="image" class="md:col-span-6 col-span-12 w-100 w-full max-w-full">
        <img class=""
             :src="image"
             :alt="image.alt">
      </div>
      <div v-else class="md:col-span-6 col-span-12 ">
        <img class="object-fill"
             :src="'http://127.0.0.1:8000/'+product.image[0].indexArray.large"
             alt="">
      </div>
      <!--end of pic-->
      <div class="col-span-12 md:hidden">
        <div class="cursor-pointer overflow-x-scroll">
          <div class=" mb-3 inline py-1 " v-for="(myImage , index) in product.image" :key="index" @click="switchImage(index)">
            <img class="object-fill inline p-1 overflow-x-scroll" style="width: 80px;height: 60px"
                 :src="myImage.url"
                 :alt="myImage.alt">
          </div>
        </div>
      </div>
      <!--      details-->
      <div class="col-span-12 md:col-span-4">
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> نام محصول :</p>
          <p>{{ product.name }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> کشور :</p>
          <p>{{ product.country }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> جنس :</p>
          <p>{{ product.material }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> سن :</p>
          <p>{{ product.age }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> رنگ :</p>
          <p>{{ product.color }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> وزن :</p>
          <p>{{ product.weight }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> طول :</p>
          <p>{{ product.length }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> عرض :</p>
          <p>{{ product.width }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> ارتفاع :</p>
          <p>{{ product.height }}</p>
        </div>
        <div class="flex justify-between border-b border-amber-200 p-1 mb-4">
          <p> قیمت :</p>
          <p>{{ product.price }}</p>
        </div>
      </div>
      <!--      end of details-->
    </section>

    <div class="p-3 mb-7" style="background-color:beige;">
      <ul class="flex flex-row md:space-x-6">
        <li class="block py-2 pr-4 pl-3 text-black">
          توضیحات
        </li>
      </ul>
    </div>
    <div class="mb-5 mx-auto whitespace-normal p-1 border-b border-amber-100-200 ">
      <div v-html="product.description"></div>
    </div>
    <div class="mb-7">
      <span class="block mb-4"> برچسب ها : </span>
      <a v-for="(tags , index) in product.tags.split(',')" :title="tags" :key="index"
         class="rounded-md text-sm" style="margin: 3px" rel="tag"
         href="">{{ tags }} / </a>
    </div>
  </div>
</template>


<script>
export default {
  data() {
    return {
      image: null,
    }
  },
  methods: {
    switchImage(index) {
      this.image = index;
    },
  },
}
</script>


P粉476883986
P粉476883986

reply all(1)
P粉759457420

I found the solution I have to add a parameter

in useFetch
const {data: productData, pending, refresh, error} = await useFetch(`http://127.0.0.1:8000/api/products/${slug}` , { initialCache: false })

Because the api caches and will not send another request, use initialCache : false it will send another request This way works fine for main product, but in products/[slug] or blog/[slug] I think you have to do this, if you have a better way please leave me a comment

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!