Subscribe on changes!

Refs as non-reactive props aren't dereferenced in v-if

avatar
Jan 5th 2024

Vue version

3.3.4

Link to minimal reproduction

<template>

       <div class="mt-4">
          <p>{{ continents.asia }}</p>
          <p>{{ continents.africa }}</p>
          <ul class="space-y-8">
            <li>
                <button @click="showList('asia')">Asia</button>
            </li>
            <li>
                <button @click="showList('africa')">Africa</button>
            </li>
            </ul>
       </div>
        <div>
        <AsiaCountries v-if="continents.asia" />
         <AfricaCountries v-if="continents.africa" />
        </div>

</template>

<script setup>
import { ref } from 'vue'
import AsiaCountries from './AsiaCountries.vue'
import AfricaCountries from './AfricaCountries.vue'


const continents = {
    asia: ref(false),
    africa: ref(false),
    europe: ref(false)
};


const showList = (listName) => {
    for (const key in continents) {
        if (key === listName) {
            continents[key].value = true;
        } else {
            continents[key].value = false;
        }
    }
};

</script>

Vue SFC Playground

Steps to reproduce

Click the buttons, the template is updated with appropriate boolean values, but v-if doesn't work as expected

What is expected?

v-if should dereference the refs and show/hide the child components accordingly

What is actually happening?

seems v-if doesn't dereference and treats the ref as truthy value

System Info

No response

Any additional comments?

I've encountered this in my code, and this is an example from a stackoverflow question where someone cannot understand why v-if doesn't work. If that's not a bug but expected behavior, could anyone point to the corresponding documentation paragraph? Anyway it looks not natural since in the other place in the template the refs are dereferenced OK.