Subscribe on changes!

When clear a reactive array object in effect function, the `array.length` is not `0`, all ways has a element in it.

avatar
May 27th 2022

Vue version

3.2.22

Link to minimal reproduction

https://github.com/vuejs/core/discussions/6017

Steps to reproduce

just copy the code to HTML file, load page in browser.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>reactivity test</title>
    <script src="https://unpkg.com/@vue/reactivity@3.2.36/dist/reactivity.global.js"></script>
    <script>
        const store = VueReactivity.ref([])
        // const store = VueReactivity.reactive({
        //     value: []
        // })

        let counterForRun = 0
        const effectRunner = VueReactivity.effect(() => {
            console.log(`effect run times is ${counterForRun}`)
            if (store.value.length > 0) {
                // do some thing...
                console.log(`store value is ${JSON.stringify(store.value)}`)
                // clear store
                // store.value.length = 0
                store.value.splice(0) // trigger effect again
            }
            counterForRun += 1
        })

        let intervalTimes = 0
        const intervalId = setInterval(() => {
            if (intervalTimes === 2) {
                clearInterval(intervalId)
                // VueReactivity.stop(effectRunner)
                return
            }
            store.value.push(intervalTimes)
            intervalTimes += 1
        }, 1000)

    </script>
</head>
<body>

</body>
</html>

image

store.value.splice(0) trigger effect callback run again, but in the effect callback, store.value.length is not 0.

Did I use @vue/reactivity it in the right way ???

What is expected?

When clear store.value, the store.value.length=0 .

What is actually happening?

Clear reactive array store, but the store.value.length=1, not 0.

System Info

5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53

Any additional comments?

Maybe I use it in the wrong way.

avatar
Sep 15th 2022

I got exactly the same problem. When splicing an element out of an reactive Array, computed values are triggered too early. The item has been sucessfully removed, but the array.length is unchanged when the computed value recompution is triggered. Which causes errors when looping over that array.

avatar
Aug 3rd 2023

This isn't really an edge-case. There should be a warning somewhere in the docs, that you should not use watch with flush: sync, or computedEager for large arrays.

And that splice(), shift(), etc. are not atomic operations with Vue.

The JSBench example here is 10 million times slower with Proxy, on my machine: https://github.com/vuejs/core/issues/3541#issuecomment-820925456

avatar
Oct 27th 2023

Fixed by #5912.