No re-rendering occurring upon updating ref value
Vue version
3.2.45
Link to minimal reproduction
https://codesandbox.io/s/epic-hellman-hrlnl7?file=/src/App.vue
Steps to reproduce
Text Input Example
- Open Link to minimal reproduction
- Type something in input field (more than 5 characters)
- ref.value has value "limit"
- input.value has another value
Checkbox Example
- Open Link to minimal reproduction
- Check the checkbox
- Click cancel in confirm modal
- ref.value has value "false"
- input.checked has value true
What is expected?
Input value updates after ref.value changed
What is actually happening?
Desynchronization between the reactive value and the value of the DOM element
System Info
No response
Any additional comments?
I've encountered a situation where updating the ref value doesn't cause the expected reaction. As far as I understand, each reference to .value initiates a subscription to the value change, and once this value has changed, a re-render should occur. The rendering engine creates an updated version of the virtual DOM, compares it with the current virtual DOM, and if any changes are detected, redraws the corresponding elements in the real DOM. In this case, it seems that the engine should respond to the change of the ref value and re-render the element, updating its value. However, for some reason, this does not happen.
I would greatly appreciate it if you could help me understand why this behavior occurs. I'm not necessarily looking for a solution right now, but I want to comprehend what exactly is happening during the re-rendering phases and why it's not working as I expect.
Also I found the same issue in vue 2 https://github.com/vuejs/vue/issues/11621 but there is no valid answer
Thank you in advance for your time and assistance.
I saw some workarounds like this in mature UI libraries
You are not actually updating the ref value. it's false
before clicking the checkbox, and after you update it, it's still false
when you cancel the prompt. So Vue does not have a reason to re-render. Nothing changed.
But the HTML Element did change already. So that's the reason why your data is now out of sync.
A possible more Vue-y solutionm than what @xrsdww linked to, would be to use something like this:
<input type="checkbox" v-model="checked" @click="guardChecked" />
const checked = ref(false);
const guardChecked = (event) => {
const isConfirmed = window.confirm("Are you sure?");
// preventing the click event's default will prevent the checkbox from togglinh its checked state.
// that will in turn prevent the input and change events from firing,
// and so the checkbox as well as the v-model value will stay as they are
if (!isConfirmed) { event.preventDefault() }
};