Readers like you help support MUO. When you make a purchase using links on our site, we may earn an affiliate commission. Read More.

The Svelte framework is one of the hottest JavaScript frameworks in the web development ecosystem. Its easy-to-grasp syntax makes it the perfect choice for those who want to create stunning web applications in a way that feels similar to vanilla JavaScript.

This guide will help you understand how Svelte actions work and how to use them. Understanding how Svelte actions work is an essential skill for anyone looking to harness the full potential of this remarkable framework.

What Are Svelte Actions?

At the most basic level, an action in Svelte is simply a JavaScript function that runs whenever an element is mounted. Svelte actions can return a JavaScript object with a destroy method that the browser calls whenever it removes an element from the Document Object Model (DOM). For example, if you want to log the inner text of a DOM element whenever the browser mounts it on the DOM, one approach is to do the following:

 <script>
  let messageShown;
  let message;
  $: messageShown ? console.log("Mounted:", message?.innerText) : "";
</script>

{#if messageShown}
  <div bind:this={message}>This is a message...</div>
{/if}

<button on:click={() => (messageShown = !messageShown)}>Toggle Message</button>

In the code block above, there are two variables in the script tag namely, messageShown and message. The browser mounts the div element only if messageShown is truthy, and the button element is responsible for controlling the state of the messageShown variable.

On the div element, there is a bind: directive that binds the host element (in this case div), to the messageShown variable. The $ symbol marks the subsequent statement as reactive—which means that any functions in the statement will rerun whenever any of the dependencies change.

In this case, the $ symbol tells the browser to listen for any changes in the subsequent statement and log the innerText of the message binding. Recall that message is bound to the div element.

That is a lot of code for such a simple problem. Svelte actions make this process of listening for the mount status of an element much simpler.

How to Create a Svelte Action

Here's how you can recreate the functionality illustrated above with an action instead. Svelte provides a use: directive that you can attach to any element in your component. The use: directive should reference the action you want to run as soon as the browser mounts the element on the DOM.

 <script>
let messageShown = false;
const notify = (node) => {
    console.log("Mounted", node.innerText);
}
</script>

{#if messageShown}
<div use:notify>
    This is a message...
</div>
{/if}

<button on:click={()=>messageShown=!messageShown}>Toggle Message</button>

In the code block above, the script tag holds a notify function that logs a message in the browser console. In the markup section, the div element has a use: directive that references the notify function.

This tells the browser to run the notify function whenever the browser mounts the div element on the DOM. Notice the node parameter in the notify function. This parameter refers to the element that the action is attached to.

Notice how much cleaner this approach looks compared to the former. The former approach works well, but what if you want to replicate this functionality across multiple elements in different components? This will lead to code duplication.

Because a Svelte action is simply a function, this means you can create a regular .js file and export your action as a module that different elements across your application can use. You can attach multiple actions to a single element, each one designed to do a specific thing. A common approach is to create a lib directory with an actions.js file that exports different actions.

 export function action1(node) {
    // Some code to run...
}

export function action2(node) {
    // Some code to run...
}

You can now import the appropriate actions wherever you need them:

 <script>
    import { action1 } from "./lib/actions"
</script>

<div use:action1>

</div>

Using the destroy Method in an Action

So, you've learned about listening for changes when the browser mounts an element on the DOM, but how can you monitor an element's removal from the DOM? As previously mentioned, in Svelte, every action has the capability to provide an object with a destroy method, enabling you to perform actions whenever the browser removes the hosting element from the DOM.

You can modify the notify function from the example earlier to return an object with a destroy method like this:

 const notify = (node) => {
  console.log("Mounted", node.innerText);
  return {
      destroy: ()=>console.log('Unmounted!')
  }
}

The function returns an object with the method destroy. When the browser removes the element, it calls the destroy method which is responsible for displaying the text Unmounted! in the console.

Passing Parameters Into an Action

When you attach an action to an element with the use: directive, Svelte automatically binds that element to a parameter (usually called node), that you can reference from your action. But you can pass other parameters into an action like this:

 <div use:action={param}></div>

If you want to reference the param variable in your action, the action should look something like this:

 function action(node, param){
    // Some code here...
}

Passing multiple parameters into an action is also possible. To do this, you have to pass in the parameters as an object.

 <div use:action={{param1, param2}}>

</div>

You can now use the parameter in your action like this:

 function action(node, {param1, param2}) {
    // Some code here...
}

Using the Update Method in an Action

In addition to the destroy method, actions can also return an update method that runs whenever its parameters change. To illustrate that, here is the code for a simple game where the computer picks a random number that is a multiple of five, and the player has to guess the number.

 <script>
let number = null;
let randomSign = Math.random() < 0.5 ? -1 : 1;
let guess = Math.floor(Math.random()*10) * 5 * randomSign;
console.log(guess);
let message = `Guess the number the computer is thinking...
It is a multiple of 5 :-)`

function evaluate(node, {number, guess}){
  return {
    update:({number, guess}) =>{
      number > guess ? message='Lower!' : message = "Higher!"
      number === guess ? message="You guessed it!" : "";
    }
  }
}
</script>

{message}
<h1 use:evaluate={{number, guess}}>
  {number}
</h1>
<button on:click={()=>number=number+5}>Increase by 5</button>
<button on:click={()=>number=number-5}>Reduce by 5</button>

In the code block above, the evaluate function is an action that returns an object with an update method. This method listens for changes in the parameters passed and returns a string based on the user's proximity to an accurate guess. There are two buttons with on:click directives that are responsible for increasing and decreasing the number.

Svelte Makes Web Development Easier

Svelte has a radical approach to building web applications. By shifting the heavy lifting from runtime to compile time, Svelte streamlines your codebase, resulting in faster, leaner, and more efficient applications.

Its elegant and intuitive syntax empowers developers to create dynamic web experiences with ease, while its reactivity system simplifies state management. SvelteKit is a meta-framework that transforms Svelte from a component/UI library into a full framework with support for routing, server-side rendering, and more.