Chupachar
@Chupachar
front-end dev

Как решить проблему исчезновения данных товаров при перезагрузке страницы во Vue.js приложении?

Проблема в том, что в имеющемся интерфейсе есть список карточек товаров и при переходе на товар по такому урл например http://localhost:5173/Product/12, я перехожу на страницу товара с его описанием, комментариями и т.д. После перезагрузки страницы на данном роуте http://localhost:5173/Product/12, товар исчезает, всё ломается и я получаю такие предупреждения:
Unhandled error during execution of render function 
  at <TheProductsPage onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouterView> 
  at <App>
  
  [Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core 
  at <TheProductsPage onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouterView> 
  at <App>


У меня есть компонент TheProductsPage.vue в котором я получаю список товаров с сервера такого вида:
//TheProductsPage.vue
<template>
   <BaseProductCard 
          v-for="(product, index) in allMainFiltersStore.sortedAndFilteredData" 
          :key="index" 
          :product="product" 
        />
</template>
<script setup>
import { useAllMainFiltersStore } from '../stores/allMainFilters.js';
const allMainFiltersStore = useAllMainFiltersStore();
const { sortedAndFilteredData } = allMainFiltersStore; //получаю отфильтрованные данные массива, с таким же успехом могу получать массив  products
</script>


//getData.js pinia
export const useAllMainFiltersStore = defineStore('allMainFilters', () => {
const products = ref([]);
onMounted(() => {
  try {
    async function getStoreData() {
      sidebarResizeStore.updateSidebarVisibility()
      const data = await productsData();
      products.value = data;
    }
    getStoreData()
  } catch (error) {
    console.error('Error:', error);
  }
})
return {
  products,
}
})

//api.js
export async function productsData() {
  const response = await fetch('http://localhost:5000/api/products');
  return getData(response)
}

По факту, с серверной стороны всё работает и массив const data = await productsData(); всегда заполнен объектами товаров. Так же вот еще доп. код, может в нём дело, с помощью которого я перехожу на id кликнутых товаров в том же компоненте TheProductsPage.vue:
const productId = ref(router.currentRoute.value.params.id);
const product = ref(getProductById(productId.value))

function getProductById(id) {
  console.log('products component: ', mainFiltersStore.products) //при первой загрузке всё ок, при перезагрузке страницы всё ломается и пустой массив в придачу
  return products.find(product => product.id == id);
}
watch(() => router.currentRoute.value.params.id, (newId, oldId) => {
  if (newId !== oldId) {
    productId.value = newId;
    product.value = getProductById(newId);
    fetchComments(newId);
  }
});

В чем может быть проблема подскажите пожалуйста. P.S. в pinia массив заполнен всегда products:Array[20] в не зависимости от поломки компонента, то есть данные где то теряются после перезагрузки.
  • Вопрос задан
  • 368 просмотров
Решения вопроса 1
Aetae
@Aetae Куратор тега JavaScript
Тлен
Во-первых: не используй onMounted внутри стора. onMounted - это хук компонента, а не стора. Оно работает только благодаря стечению обстоятельств.
Во вторых: products должны быть ref. Сейчас они не реактивны(никак не реагируют на изменения). При этом ты присваииваешь массиву value. То что это хоть как-то работало - очередное чудо.
В-третьих: ты должен учитывать, что какое-то время данные будут грузиться и показывать лоадер пока их нет.

В общем если загрузка должна начинаться в лбом случае при первой инициализации store'a(обычно загрузку привязывают к маршрутам или компонентам), то выглядеть оно будет как-то так:
export const useAllMainFiltersStore = defineStore('allMainFilters', () => {
  const products = ref([]);

  try {
    async function getStoreData() {
      sidebarResizeStore.updateSidebarVisibility()
      const data = await productsData();
      products.value = data;
    }
    getStoreData()
  } catch (error) {
    console.error('Error:', error);
  }
  
  return {
    products,
  }
})


В компоненте:
const route = useRoute();
// продукт делаем вычисляемым, чтоб не городить вотчеров
const product = computed(() => getProductById(route.params.id));

function getProductById(id) {
  console.log('products component: ', mainFiltersStore.products) //при первой загрузке всё ок, при перезагрузке страницы всё ломается и пустой массив в придачу
  return products.find(product => product.id == id);
}

watch(product, current => {
  // проверяем что продукт есть
  if (current) fetchComments(current.id);
}, { immediate: true })
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы