You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt页面首次加载无法渲染Pinia Store产品数组问题求助

问题

基于Nuxt的产品列表页面调用Pinia Store中的fetchProducts()获取数据,首次访问时产品列表无法渲染。从截图可见产品已加载并存于Pinia Store,但页面上的products数组为空;返回首页再进入产品页面则可正常渲染,控制台无报错。

页面代码:

<script setup>
import { storeToRefs}   from "pinia";
import { useShopStore } from '@/stores/shop'

const shop = useShopStore();
shop.fetchProducts();
const {products} = storeToRefs(shop)
const hasProducts = computed(() => products.value.length > 0);

</script>

<template>
    <NuxtLayout>
        <div class="container">
            <h2>Products</h2>
            <div class="container" v-if="hasProducts">
                  <div class="row row-cols-1 gap-3">
                    <ProductCard :product="product" v-for="product in products" :key="product.id"/>
                </div>
            </div>
            <div v-else>
                <h3>Products NOT loaded</h3><br>
            </div>
        </div>
    </NuxtLayout>
</template>

Pinia Store代码:

import { defineStore } from 'pinia'

import Product  from "@/models/Product";

export const useShopStore = defineStore('shop', {
    state: () => ({
        products: [] as Product[]
    }),
    actions: {
        fetchProducts: async function () {
            try {
                const {data} = await useFetch('https://fakestoreapi.com/products');
                //TODO - fix this  typescript error `TS2352: Conversion of type 'Ref<unknown>' to type 'Product[]' may be a mistake because neither type sufficiently overlaps with the other.`
                // @ts-ignore
                this.products = data as Product[];
            } catch (error) {
                return error
            }
        },
    }
})

排查与修复建议

1. 处理异步调用的状态同步

fetchProducts是异步方法,首次执行时页面不会等待它完成就直接渲染,导致首次渲染时products还是空数组。需要添加加载状态优化渲染逻辑:

  • 在Store的state中新增isLoading标记:
state: () => ({
    products: [] as Product[],
    isLoading: false
}),
actions: {
    async fetchProducts() {
        this.isLoading = true;
        try {
            const {data} = await useFetch('https://fakestoreapi.com/products');
            this.products = data.value as Product[];
        } catch (error) {
            console.error('加载产品失败:', error);
        } finally {
            this.isLoading = false;
        }
    }
}
  • 页面中更新渲染逻辑:
<script setup>
// ...
const {products, isLoading} = storeToRefs(shop);
const hasProducts = computed(() => !isLoading.value && products.value.length > 0);
</script>

<template>
    <NuxtLayout>
        <div class="container">
            <h2>Products</h2>
            <div v-if="isLoading">加载中...</div>
            <div class="container" v-else-if="hasProducts">
                  <div class="row row-cols-1 gap-3">
                    <ProductCard :product="product" v-for="product in products" :key="product.id"/>
                </div>
            </div>
            <div v-else>
                <h3>Products NOT loaded</h3><br>
            </div>
        </div>
    </NuxtLayout>
</template>

2. 修正useFetch的数据赋值

useFetch返回的data是Ref对象,直接赋值会导致Store中存储的是Ref而非实际数组,需取出data.value再赋值:

this.products = data.value as Product[];

3. 调整页面数据加载时机

在Nuxt中,可通过onMounted或useAsyncData确保数据加载完成后再渲染:

  • 方案一:用onMounted调用异步方法
<script setup>
import { storeToRefs, onMounted } from "pinia";
import { useShopStore } from '@/stores/shop'

const shop = useShopStore();
const {products, isLoading} = storeToRefs(shop);
const hasProducts = computed(() => !isLoading.value && products.value.length > 0);

onMounted(async () => {
    await shop.fetchProducts();
});
</script>
  • 方案二:结合Nuxt的useAsyncData
<script setup>
import { storeToRefs } from "pinia";
import { useShopStore } from '@/stores/shop'

const shop = useShopStore();
const {products, isLoading} = storeToRefs(shop);
const hasProducts = computed(() => !isLoading.value && products.value.length > 0);

useAsyncData('products', async () => {
    if (products.value.length === 0) {
        await shop.fetchProducts();
    }
});
</script>

4. 修复TypeScript类型错误(可选)

移除@ts-ignore,给useFetch指定返回类型:

const {data} = await useFetch<Product[]>('https://fakestoreapi.com/products');
this.products = data.value || [];

内容的提问来源于stack exchange,提问作者AlexeiP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:45:36