Skip to content

Commit

Permalink
Update 04-$effect.md
Browse files Browse the repository at this point in the history
  • Loading branch information
sacrosanctic authored Dec 24, 2024
1 parent 1d773ef commit f168ea1
Showing 1 changed file with 39 additions and 27 deletions.
66 changes: 39 additions & 27 deletions documentation/docs/02-runes/04-$effect.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
NOTE: do not edit this file, it is generated in apps/svelte.dev/scripts/sync-docs/index.ts
title: $effect
---

Expand Down Expand Up @@ -179,7 +180,13 @@ Apart from the timing, `$effect.pre` works exactly like `$effect`.

## `$effect.tracking`

The `$effect.tracking` rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template ([demo](/playground/untitled#H4sIAAAAAAAACn3PwYrCMBDG8VeZDYIt2PYeY8Dn2HrIhqkU08nQjItS-u6buAt7UDzmz8ePyaKGMWBS-nNRcmdU-hHUTpGbyuvI3KZvDFLal0v4qvtIgiSZUSb5eWSxPfWSc4oB2xDP1XYk8HHiSHkICeXKeruDDQ4Demlldv4y0rmq6z10HQwuJMxGVv4mVVXDwcJS0jP9u3knynwtoKz1vifT_Z9Jhm0WBCcOTlDD8kyspmML5qNpHg40jc3fFryJ0iWsp_UHgz3180oBAAA=)):
```js
// @noErrors
const $effect.tracking: boolean;
```

The `$effect.tracking` rune is `true` when used inside a reactive context, such as an `$effect`, `$effect.pre` or in your svelte markup ([demo](/playground/untitled#H4sIAAAAAAAACn3PwYrCMBDG8VeZDYIt2PYeY8Dn2HrIhqkU08nQjItS-u6buAt7UDzmz8ePyaKGMWBS-nNRcmdU-hHUTpGbyuvI3KZvDFLal0v4qvtIgiSZUSb5eWSxPfWSc4oB2xDP1XYk8HHiSHkICeXKeruDDQ4Demlldv4y0rmq6z10HQwuJMxGVv4mVVXDwcJS0jP9u3knynwtoKz1vifT_Z9Jhm0WBCcOTlDD8kyspmML5qNpHg40jc3fFryJ0iWsp_UHgz3180oBAAA=)):


```svelte
<script>
Expand All @@ -188,12 +195,16 @@ The `$effect.tracking` rune is an advanced feature that tells you whether or not
$effect(() => {
console.log('in effect:', $effect.tracking()); // true
});
$effect.pre(() => {
console.log('in effect.pre:', $effect.tracking()); // true
});
</script>
<p>in template: {$effect.tracking()}</p> <!-- true -->
```

This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects. Here's a `readable` function that listens to changes from a callback function as long as it's inside a tracking context:
This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects. Here's a `readable` function that listens to changes from a callback function as long as it's inside a reactive context:

```ts
import { tick } from 'svelte';
Expand All @@ -209,31 +220,32 @@ export default function readable<T>(

return {
get value() {
// If in a tracking context ...
if ($effect.tracking()) {
$effect(() => {
// ...and there's no subscribers yet...
if (subscribers === 0) {
// ...invoke the function and listen to changes to update state
stop = start((fn) => (value = fn(value)));
}

subscribers++;

// The return callback is called once a listener unlistens
return () => {
tick().then(() => {
subscribers--;
// If it was the last subscriber...
if (subscribers === 0) {
// ...stop listening to changes
stop?.();
stop = null;
}
});
};
});
}
// If not in a reactive context
if (!$effect.tracking()) return value

// If in a reactive context ...
$effect(() => {
// ...and there's no subscribers yet...
if (subscribers === 0) {
// ...invoke the function and listen to changes to update state
stop = start((fn) => (value = fn(value)));
}

subscribers++;

// The return callback is called once a listener unlistens
return () => {
tick().then(() => {
subscribers--;
// If it was the last subscriber...
if (subscribers === 0) {
// ...stop listening to changes
stop?.();
stop = null;
}
});
};
});

return value;
}
Expand Down

0 comments on commit f168ea1

Please sign in to comment.