🏠
Author: mary.my.id (did:plc:ia76kvnndjutgedggx2ibrem)

Record🤔

uri:
"at://did:plc:ia76kvnndjutgedggx2ibrem/com.whtwnd.blog.entry/3kzqrbgxbeg2b"
cid:
"bafyreiagyetxzvpkrf2lzud24wmldld46hsoqirexqnqelwmust3nlytge"
value:
$type:
"com.whtwnd.blog.entry"
theme:
"github-light"
title:
"Vue..."
content:
"So, I've been at work and noticed that our Vue 3 app is complaining with this error.

```
Uncaught (in promise) TypeError: can't access property "stop", this.effects[i] is undefined
```

What's going on? from the stack trace I know that this is coming from an effect scope[^1] trying to stop all of its registered effects. I've searched through Vue's source code and couldn't find any trace of *any code* setting `undefined` to the array values, however, there is [one thing](https://github.com/vuejs/core/blob/main/packages/reactivity/src/effectScope.ts#L119-L121) that stood out!

```ts
for (i = 0, l = this.effects.length; i < l; i++) {
    this.effects[i].stop()
}
```

Notice the variable that is holding the effects array's length? That's a common optimization trick to avoid having to access it on every iteration, which can be a big boost for very large arrays. After some debugging I've verified that what's happening is an out-of-bound array access, so that sums the error, but why is it happening?

---

A lot of people might have known this already, but I am a massive [Solid.js](https://solidjs.com/) user, it has signals which are essentially the same thing as Vue's refs, the big thing that Solid.js has is nested reactivity, where you can create effects within effects!

```ts
const [count, setCount] = createSignal(0);
const [enabled, setEnabled] = createSignal(false);

// only log `count` if it's been enabled
createEffect(() => {
  if (enabled()) {
    createEffect(() => {
      console.log(count());
    });
  }
});
```

If `enabled` is `true`, then the effect within it gets created, and if it turns to `false` it'll be destroyed. This ability to nest is powerful, you can easily think of solutions that'd either require this or would've been heavily simplified with this sort of thing.

Vue has the same fine-grained reactivity that Solid.js has, wouldn't it be possible to do same in Vue?

```ts
const count = ref(0);
const enabled = ref(false);

watch(enabled, (isEnabled, _prev, cleanup) => {
  if (isEnabled) {
    cleanup(
      watch(count, ($count) => {
        console.log($count);
      }, { immediate: true })
    );
  }
}, { immediate: true })
```

Well, the code looks awkward and all, but it does seem like it'd work, no?

Not quite, this is exactly what caused the error from earlier.

[^1]: Effect scopes is how Vue keeps track of effects registered within a component, a scope gets instantiated during component creation, and the component's setup function gets run inside the scope."
createdAt:
"2024-08-15T10:29:57.703Z"
visibility:
"author"