Search code examples
vuejs3vue-composition-apivue-script-setup

Why some variables are inacessible in onMounted Lifecyle Hook in vue3 composition API?


I'm kinda new to composition API in vue3 and I'll be glad if someone could explain to me why...

this works:

<template>
  <h1>{{ foo }}</h1>
</template>

<script setup>
import { ref, onMounted } from "vue";

const foo = ref('');

onMounted(() => {
  foo.value = 'bar';
});
</script>

and this don't:

<template>
  <h1>{{ foo }}</h1>
</template>

<script setup>
import { onMounted } from "vue";

let foo;

onMounted(() => {
  foo = 'bar';
});
</script>

I can't access foo inside onMounted neither I am able to declare a variable inside onMounted and access it outside the lifecycle hook. Why does it happen?


Solution

  • It's not that foo isn't updating, because it is, it's just not triggering a rerender of the UI because foo is not reactive. At the time the screen is initially rendered (right before onMounted runs), foo has no value, so that's what is rendered. Vue is not tracking changes to foo, so even when foo changes, it's not reason enough for Vue to rerender the screen. If it was reactive, Vue would rerender the screen every time foo changes, hence why the first example works.

    Vue only updates the UI when something reactive changes. If non-reactive variables update, Vue doesn't care. If something else reactive caused a rerender, <h1>{{ foo }}</h1> would update to show the latest value of foo

    Example:

    <template>
      <h1>{{ foo }}</h1>
      <div @click="rerender">click me {{ bar }}</div>
    </template>
    
    <script setup>
    import { onMounted, ref } from 'vue'
    
    let foo
    
    let bar = ref(0)
    const rerender = () => {
      bar.value++
    }
    
    onMounted(() => {
      foo = 'bar'
    })
    </script>
    
    

    The Vue docs go into more in-depth explanation as to how reactivity works and is definitely worth a read!