I have this simple 2 component vue app : (nuxt, composition api and ts)
Parent :
<template>
<input type="text" v-model="txt">
<Child :txt="txt"></Child>
</template>
<script lang="ts" setup>
let txt = ref("")
</script>
Child :
<template>
<p>{{ txt }}</p>
<p>{{ txt + " 1" }}</p>
<p>{{ txtComputed }}</p>
</template>
<script lang="ts" setup>
const { txt } = defineProps<{
txt: string
}>()
let txtComputed = computed(() => {
return txt + " 1"
})
</script>
I would like the txtComputed to change according to the txt. But it's stuck at the first value (just " 1"
)
If I have more complex logic than just adding 1, I'd like to not code it in the html.
So why is the computed not working with props ?
The returned object from defineProps
is a reactive object, similar to ones created with reactive(). When you destructure it, you bind the current values to variables - those values will not be reactive anymore.
As the documentation states:
you need to always access props as
props.x
in order to retain reactivity. This means you cannot destructuredefineProps
because the resulting destructured variables are not reactive and will not update.
So if you want to preserve reactivity, you have to assign the result from defineProps directly:
const props = defineProps<...>()
const txtComputed = computed(() => props.txt + " 1")
Alternatively, you can turn individual props into refs with toRef()
or all at once with toRefs()
.