Closed panstromek closed 1 year ago
From some further testing, it looks like v-model
will replace the whole Ref
with a primitive boolean
value after you press the checkbox. It seems that the root object is assumed to be reactive but it isn't in this case.
I feel like I have an intuition for why this happens, but it's a bit unfortunate footgun, combined with the recommendation to return non-reactive objects from composables (my original intent was to create some useSetting
composable here).
<template>
<div>
<div v-for="setting in settings" :key="setting.key">
<input v-model="setting.val.value" type="checkbox" >
</div>
Checkbox changed times: {{changedTimes}}
</div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
const singleSetting = {
key: 'setting-1',
val: ref(false),
}
const changedTimes = ref(0)
watch(singleSetting.val, (current, previous) => {
console.log('changed', current, previous)
changedTimes.value++;
})
const settings = [singleSetting]
</script>
I don't think it's a bug. In your usage method, in the template, ref will not be unwrapped automatically, you need to access .value
by yourself
(https://vuejs.org/guide/essentials/reactivity-fundamentals.html#ref-unwrapping-in-templates)
In your demo there are typo mistakes and ref syntax errors
const changedTimes = ref(0)
watch(singleSetting.val, (current, previous) => {
console.log('changed', current, previous)
changedTime++;
})
I don't think it's a bug. In your usage method, in the template, ref will not be unwrapped automatically, you need to access
.value
by yourself (https://vuejs.org/guide/essentials/reactivity-fundamentals.html#ref-unwrapping-in-templates)
I tried that and it generates an error. But doing it in the reproduction didn't, I'll have to investigate in the original code. Also, this link is dead, the chapter is not present.
In your demo there are typo mistakes and ref syntax errors
const changedTimes = ref(0) watch(singleSetting.val, (current, previous) => { console.log('changed', current, previous) changedTime++; })
oh, sorry. I messed it up when reducing the problem.
Looks like the problem was leftower state from hot reload (changing to .value
access) tried to set value
on raw boolean, that was left from previous version with ref that was assumed to be unwrapped. If I refresh the page, it works correctly (when accessing .value
).
Thanks for looking at this.
Vue version
vue@3.3.4
Link to minimal reproduction
https://play.vuejs.org/#eNplUUtugzAQvcrIG4hCknZLk0hVj9DuShfUGcCKsS3b0EaIu3cMriDKzvN7Pw/s1Zh93yHL2dFja2Tp8VwogONF9NNjfkK/q7Q9Fcyh90LVIBTEpysY5Fe8LcM9VQWL1wFAKNN5gmj1BeVqry8lHfubQWryBvn1W/9S55/4sIh4i1PgTalqvIAXLbochiE2PkI9jpP2eHc8rCxR6bgVxgfdnQFJV8TqST5NRWu09TCAxSqDn9LzBkaorG6hYJRPwV4CBNfKEQBpl/gekzjBEEjJcw5JdLZ7TrLQJIN5gEyrUjrcUI8EziBr2YQRlp42gWMiT+84QlAZpLyzFpXPwFjshe7cBk7nmT1gaol7qes0idBJBo8X0/JCvd2Sr3Hijd7ip5KkzzsNX1OEhzlDSoyNf6flx1k=
Steps to reproduce
Click the checkbox few times
What is expected?
Counter should be incremented when clicking on the checkbox (also a log in the console should be shown)
What is actually happening?
Counter is not incremented and no log appear in the console
System Info
No response
Any additional comments?
No response