# reactivity

vue watches the value, react re-runs the function. almost every difference
between the two frameworks falls out of that one decision.

## what a ref actually is

`ref(0)` returns an object with a `value` property behind a proxy. reading
`count.value` registers whoever is reading it as a dependency. writing to it
notifies exactly those readers, and nothing else runs.

```js
const count = ref(0);

watchEffect(() => console.log(count.value)); // registers itself on read
count.value++;                               // only that effect re-runs
```

that is the whole model. the `.value` that everyone complains about is the price
of it: a plain number cannot be proxied, so the value has to live inside
something vue can intercept.

`reactive({ count: 0 })` proxies the object itself, so there is no `.value`. it
only works on objects, and it is the reason for the trap further down.

## why there is no dependency array

in react, a change re-runs the component function and everything in it. the
framework has no idea which values your effect touched, so you tell it:

```jsx
useEffect(() => { console.log(count); }, [count]);
```

get that list wrong and the effect reads a stale value. see
[`useState`](../../react/hooks/usestate.md) for why the value is stale rather
than simply old.

vue collected the dependencies while the effect ran, so there is no list to
write and no list to get wrong:

```js
watchEffect(() => { console.log(count.value); });
```

the same reason explains the rest of the gap. no `useCallback`, because the
component function does not re-run. no stale closures, because there is one
value and not a snapshot per render. no memoization burden, because a write
notifies its readers instead of re-rendering a subtree.

## the trap: destructuring loses the proxy

reactivity lives in the proxy, so pulling a value out of it leaves the
reactivity behind.

```js
const state = reactive({ count: 0 });
const { count } = state;   // count is now a plain 0, forever
```

`count` is a copy taken at that moment. later writes to `state.count` update
nothing, and nothing warns you.

```js
const { count } = toRefs(state); // keeps the connection
```

the same thing happens with props, which is why `toRefs(props)` shows up in
almost every composable that takes them.

## when it bites

passing reactive state through a plain function, spreading it into a new object,
or storing it in a normal array. all three copy the value out and the connection
is gone. if a value stopped updating and nothing looks wrong, this is almost
always what happened.
