UPDATE:
I have achieved the desired behavior in my app the the MCV by changing resetArray
:
function resetArray() {
// myArray.value = [] // old version
myArray.value.length = 0 // new version
}
But I still don't understand why my MCV doesn't work.
ORIGINAL POST:
Background
In an app I am building, I store data in an a ref
, created as const myArray = ref([])
, which takes the form of an array of objects. This array is only changed in the following ways:
myArray.value[index] = {key: value}
myArray.value = []
.
In particular, at no time is an object in myArray
modified, it is either created or replaced.
I later added a watch
which took action on every to myArray.value
. I discovered that after resetting myArray
to []
, the watcher stopped getting called.
Things I have tried:
- I confirmed that my usage of
ref
follows the guidelines in this SO answer regardingref
vsreactive
. - Refactoring to use
watchEffect
instead ofwatch
. Did not help. - Refactoring to use
reactive
rather thanref
. Did not help.
My Issue
In the MCV below, modifying myArray
by calling addToArray
works as intended: myArray.length
is rendered and the first watch
is triggered.
Calling resetArray
triggers only the second watch
, but the first watch IS NOT triggered when addToArray
is called afterwards.
My Question
How can I both keep the ability to set myArray
to []
and trigger actions every time myArray
changes?
My MCV
View my MCV on Vue SFC Playground
The below code is the content of App.vue
in a Vue project created with npm init vue@latest
:
<script setup>
import {ref, watch} from "vue"
const myArray = ref([])
function addToArray() {
myArray.value.push("1")
}
function resetArray() {
myArray.value = []
}
watch(myArray.value, () => {
console.log("CLICKED!")
})
watch(myArray, () => {
console.log("RESET! clicked won't get called again!")
})
</script>
<template>
{{myArray.length}}<br />
<button @click="addToArray">CLICK ME</button><br />
<button @click="resetArray">RESET</button>
</template>
CodePudding user response:
When watching a
ref
, use theref
itself -- not itsvalue
property -- as the watch source (the 1st argument towatch()
).To observe new array assignments or item additions/removals, pass the
deep:true
option (the 3rd argument towatch()
):
watch(
myArray 1️⃣,
() => { /* handle change */ },
{ deep: true } 2️⃣
)