# Effects

Source: https://signy.dev/documentation/1/reactivity/effects/

Run code when the signals it reads change.

## effect()

An effect runs once, tracks the signals it reads, and runs again when one of them changes. Its first run happens in a microtask.

```js
effect(() => {
  document.title = `${this.count.value} items`;
});
```

Create effects in a component's `setup()`, so the component owns them and disposes them on unmount.

```js
const { Component, Signal, application, html, effect } = Signy;

class Logger extends Component {
  count = new Signal(0);
  log = new Signal([]);

  setup() {
    effect(() => {
      const count = this.count.value;
      this.log.set((lines) => [...lines.slice(-2), `count is ${count}`]);
    });
  }

  render() {
    return html`
      <button onClick=${() => this.count.set((c) => c + 1)}>Add one</button>
      <p>${() => this.log.value.join(", ")}</p>
    `;
  }
}

application(Logger).mount("#effect-log");
```

## onCleanup()

Call `onCleanup()` inside an effect to undo its previous run, such as a timer or a listener. It runs before the next run and when the effect is disposed.

```js
effect(() => {
  const delay = this.delay.value;
  const timer = setInterval(() => this.tick(), delay);
  onCleanup(() => clearInterval(timer));
});
```

## on()

`on(source, fn)` tracks only the source and passes the new and previous values. `defer: true` skips the first run.

```js
effect(
  on(() => this.page.value, (page, previous) => {
    console.log(previous, '->', page);
  }, { defer: true })
);
```

## untrack()

Read a signal inside an effect without depending on it.

```js
effect(() => {
  save(this.draft.value, untrack(() => this.user.value));
});
```
