I have a product list and form on my vue application. When the product list is opened, a request is made to my rest api and fills the results in a pinia store object (products
). This works great so far and the products get added to my state.
I can also request a single product using my api by passing the product_id
to it. This is how I handled the product form at first, but realized it would be more efficient to filter the products
store object and get the single product from state rather than make another api request when the form component loads. I created a new action to do just this but I can't get it to work. Here is my store with the action:
//ProductStore.js
import { defineStore } from "pinia";
import { getProducts } from "@/composables/products";
export const useProductStore = defineStore("product", {
state: () => ({
products: [], //for my products list component
product: {}, //for my product form component
attributes: [],
loading: false,
error: "",
}),
actions: {
findProduct(id) { //find single product in store
this.product = this.products.find((product) => product.id === id);
},
async fetchProducts() { // retrieve all products from api
this.loading = true;
const { products, error } = await getProducts(); //api call
this.products = products;
this.error = error;
this.loading = false;
},
}
});
Here is my product form component I'm trying to filter the products
store to get a single product
and bind with the form:
// ProductForm.vue
<template>
<input v-model="product.name" type="text" />
<input v-model="product.desc" type="text" />
</template>
<script setup>
import { onMounted } from "vue";
import { storeToRefs } from "pinia";
import { useProductStore } from "@/stores/ProductStore";
const props = defineProps({
id: String,
});
const store = useProductStore();
const { product, error, loading } = storeToRefs(store);
onMounted(() => {
store.findProduct(props.id);
console.log(product);
});
</script>
When I console.log(product)
it appears I get the ref() to the product store object but without the value property:
When I run all of this I get the error: Uncaught (in promise) TypeError: $setup.product is undefined
I'm completely aware this is due to my poverty of knowledge with vue 3 composition API and pinia. I can't figure out what is going on.
CodePudding user response:
Well I think I figured it out... in my ProductForm
component I was bringing in the prop for the product_id
:
const props = defineProps({
id: String,
});
And I was invoking my action like this:
store.findProduct(props.id);
I started wondering if the prop being a string (since it comes from url) was causing the issue. So I used:
store.findProduct(parseInt(props.id));
which immediately returned the single product into my component. So I ended up modifying my routes file to handle the parse for me:
// @/routes/index.js
{
name: "Product",
path: "/products/:id",
component: () => import("@/components/ProductForm"),
props: route => ({ id: Number(route.params.id) }),
},