Svelte Component Lifecycle Hooks
Tags: svelte, webdev, programming, javascript
Published: 2021-01-28 21:41:08

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Svelte is an up and coming front end framework for developing front end web apps.

It’s simple to use and lets us create results fast.

In this article, we’ll look at the lifecycle hooks of a Svelte component.

### Component Lifecycle

Every Svelte component has a lifecycle. It starts when it’ created and ends when it’s destroyed.

There’re a handful of functions that allows us to run code at key moments of the lifecycle.

The most frequently used is `onMount` . It’s run after the component is first rendered to the DOM.

We can add a `onMount` handler to our component as follows:

```
<script>
  import { onMount } from "svelte";

  let joke = { value: { joke: "" } };

  onMount(async () => {
    const res = await fetch(`https://api.icndb.com/jokes/20`);
    joke = await res.json();
  });
</script>

<p>{joke.value.joke}</p>
```

The code above calls the Chuck Norris API to get a joke when the component loads.

Then we display it after it’s loaded.

### onDestroy

`onDestroy` ‘s callback is called when the when the component is being destroyed.

Cleanup code and anything else that runs when the component can go into `onDestroy` ‘s callback.

For instance, we can write:

```
<script>
  import { onDestroy } from "svelte";

  let seconds = 0;
  const interval = setInterval(() => seconds++, 1000);

  onDestroy(() => clearInterval(interval));
</script>

<p>Seconds: {seconds}</p>
```

In the code above, we call `setInterval` , which returns an interval ID object which we set as the value of `interval` .

Then when the component is being destroyed, we call `clearInterval` to clear the interval object from memory by passing `interval` into `clearInterval` in the `onDestroy` callback.

### `beforeUpdate and afterUpdate`

`beforeUpdate` runs immediately before the DOM has been updated.

`afterUpdate` is used for running code once the DOM is in sync with our data.

For instance, if we want to scroll to the bottom of the div if the div overflows the window height, we can write the following code:

```
<script>
  import { beforeUpdate, afterUpdate } from "svelte";
  let div;
  let autoscroll;
  let arr = [];
  setTimeout(() => {
    arr = new Array(100).fill("foo");
  }, 100);

  beforeUpdate(() => {
    autoscroll = div && div.offsetHeight + div.scrollTop > div.scrollHeight - 20;
  });

  afterUpdate(() => {
    if (autoscroll) {
      window.scrollTo(0, div.scrollHeight);
    }
  });
</script>

<div bind:this={div}>
{#each arr as a}
<p>{a}</p>
{/each}
</div>
```

The code:

```
div && div.offsetHeight + div.scrollTop > div.scrollHeight - 20
```

checks if the height of the div is bigger than the scroll height, which includes the height that’s not visible on the screen.

Then in the `afterUpdate` callback, we can scroll to the bottom of the div if there’s overflow as returned by the boolean above.

### Tick

`tick` is a function that returns a promise that resolves as soon as any pending state changes have been applied to the DOM.

When the component state is invalidated in Svelte, it doesn’t update the DOM immediately. It waits until the next microtask to see if there’re any changes that need to be applied.

This allows the batching of updates.

When we select a range of text in the text area and hit the tab key to toggle its case, then the current selection is cleared and the cursor jumps to the end.

We can retain the selection after the tab key is pressed by in a Textarea by writing the following code:

```
<script>
  import { tick } from "svelte";

let text = "";
  async function handleKeydown(event) {
    if (event.which !== 9) return;
    event.preventDefault();

    const { selectionStart, selectionEnd, value } = this;
    const selection = value.slice(selectionStart, selectionEnd);

    const replacement = /[a-z]/.test(selection)
      ? selection.toUpperCase()
      : selection.toLowerCase();

    text =
      value.slice(0, selectionStart) + replacement + value.slice(selectionEnd);
    await tick();
    this.selectionStart = selectionStart;
    this.selectionEnd = selectionEnd;
  }
</script>

<textarea bind:value={text} on:keydown={handleKeydown}></textarea>
```

In the code above we have the `handleKeydown` to see if the tab key is pressed.

We keep the text from changing by setting the `text` to the same content as before.

If it is, then we set the `selectionStart` and `selectionEnd` after `tick` is called to retain the selection.

### Conclusion

We can use the lifecycle methods to run the code we want during a stage of the lifecycle.

There’s one for when the component loaded, one for when a component is destroyed, 2 for DOM updates, and one for when the component’s state is updated.