DEV Community

John Au-Yeung
John Au-Yeung

Posted on • Originally published at thewebdev.info

Svelte Component Lifecycle Hooks

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

The code:

div && div.offsetHeight + div.scrollTop > div.scrollHeight - 20
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)