jeffspurlock
jeffspurlock

Reputation: 21

Watch a Vue 3 prop to trigger a dom update

I'm building my first project with Nuxt, and I'm running into an issue. I have a component (lets call it variant-selector) to select product variants that passes and event up to the parent component (product-view) and sets a 'selectedVariant' variable to the selected variant id, and then passes this variable into the another child component (variant-display). In my component for variant display, I have two props, the entire product object and the selectedVariant. I want to watch the selected variant and update the image src based on the selection in the variant-selector component.

Code below:

product-view.vue

<script setup>
const props = defineProps(['product'])
const selectedVariant = ref(props.product.variants.edges[0].node.id)
function updateVariant(variantId){
    selectedVariant.value = variantId 
    console.log(variantId)
}
</script>
<template>
    <div class="wrapper">
        <variant-display 
            :product="product" 
            :selectedVariant="selectedVariant"/>
        <variant-selector 
            @select-variant="updateVariant" 
            :list="product.variants.edges"/>
    </div>
</template>

variant-selector.vue

<script setup>
const props = defineProps(['list'])
const emit = defineEmits(['select-variant'])
</script>
<template>
    <div class="variant-selector">
        <v-btn 
            v-for="(variant, i) in list" 
            :key="i"
            @click.stop="$emit('select-variant', variant.node.id)" 
        >{{ variant.node.selectedOptions[0].value }}</v-btn>
    </div>
</template>

variant-display.vue

<script setup>
const props = defineProps(['selectedVariant', 'product'])
const heroImage = ref(props.product.variants.edges[0].node.image.url)
watch(props.selectedVariant, (newVariantId) => {
    props.product.variants.edges.forEach((variant)=>{
        if(variant.node.id === newVariantId){
            heroImage.value = variant.node.image.url
        }
    })
})
</script>
<template>
    <h1>{{ product.title }}</h1>
    <img :src="heroImage" />
    <div>variant: {{ selectedVariant }}</div>
</template>

When i test this, i expected the tag to update with the correct image when i click either button in the variant-selector component. I also have that <div>variant: {{ selectedVariant }}</div> in there to watch the value of the selectedVariant prop change when i click the selector component, and it is changing the value like its supposed to, but in the dev console, i'm getting a Vue Warn that props.selectedVariant is not a valid watch source. It says it must be a ref, but props.selectedVariant is a ref, and i can see that in action with that tag updating.

So... why does watch() not trigger on the prop update?

Upvotes: 0

Views: 149

Answers (1)

jeffspurlock
jeffspurlock

Reputation: 21

Well, i finally found the right piece of the documentation to answer my question. Thought i had read through it all thoroughly but missed this.

I had to add let { selectedVariant } = toRefs(props) in the setup on variant-display.vue

Upvotes: 0

Related Questions