Svelte and SvelteKit course ยท Module 10: Actions

Updating Parameters

2 min read ยท
In this lesson3

update() - React to parameter changes

An action is called only once. When the parameter changes, Svelte does not call it again - instead it calls the update() method of the returned object with the new value:

export function tooltip(node, text) {
  let tooltipEl;
  let currentText = text;

  // ... show/hide logic

  return {
    update(newText) {
      currentText = newText;
      if (tooltipEl) {
        tooltipEl.textContent = newText;
      }
    },
    destroy() {
      // cleanup
    }
  };
}
<script>
  import { tooltip } from './actions.js';

  let message = $state('Initial text');
</script>

<input bind:value={message} />
<button use:tooltip={message}>
  Hover me
</button>

Object as parameter

export function draggable(node, options = {}) {
  let { axis = 'both', bounds = null } = options;

  // ... logic

  return {
    update(newOptions) {
      axis = newOptions.axis ?? 'both';
      bounds = newOptions.bounds ?? null;
    },
    destroy() {
      // cleanup
    }
  };
}
<div use:draggable={{ axis: 'x', bounds: 'parent' }}>
  Drag me horizontally
</div>

New: attachments ({@attach})

Since Svelte 5.29 you can use attachments instead of actions. An attachment is a function that receives the element and may return a cleanup function. Unlike an action it is fully reactive: when state used in its call changes, Svelte cleans it up and runs it again, so you do not need update().

<script>
  let message = $state('Initial text');

  function tooltip(text) {
    return (node) => {
      node.title = text;
      return () => node.removeAttribute('title');
    };
  }
</script>

<input bind:value={message} />
<button {@attach tooltip(message)}>Hover over me</button>

Actions (use:) are still fully supported and you will find them in many libraries, which is why this location practises them.

Code for this lesson: App.svelte
<script>
  // Actions with events - click outside, longpress
  import { clickOutside } from './actions.js';
  import { longpress } from './actions.js';

  let modalOpen = $state(false);
  let message = $state('');

  function handleClickOutside() {
    modalOpen = false;
  }

  function handleLongpress() {
    message = 'Long press detected!';
    setTimeout(() => message = '', 2000);
  }
</script>

<main class="actions-demo">
  <h1>Actions with events</h1>

  <section>
    <h2>use:clickOutside</h2>
    <button onclick={() => modalOpen = true}>Open modal</button>

    {#if modalOpen}
      <div class="overlay">
        <div class="modal" use:clickOutside onoutclick={handleClickOutside}>
          <h3>Modal</h3>
          <p>Click outside me to close</p>
        </div>
      </div>
    {/if}
  </section>

  <section>
    <h2>use:longpress</h2>
    <button
      use:longpress={500}
      onlongpress={handleLongpress}
    >
      Hold 500ms
    </button>
    {#if message}
      <p class="message">{message}</p>
    {/if}
  </section>
</main>

<style>
  .actions-demo {
    font-family: 'Georgia', serif;
    max-width: 500px;
    margin: 0 auto;
    padding: 2rem;
    background: #1a1a2e;
    color: #e8e8f7;
    min-height: 100vh;
  }

  h1 {
    color: #7cb3f0;
    text-align: center;
  }

  section {
    background: rgba(124, 179, 240, 0.1);
    border: 1px solid #7cb3f0;
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
  }

  h2 {
    color: #7cb3f0;
    font-size: 1rem;
    margin-top: 0;
  }

  button {
    padding: 0.75rem 1.5rem;
    background: #3a5f8a;
    color: #e8e8f7;
    border: 1px solid #7cb3f0;
    border-radius: 4px;
    cursor: pointer;
  }

  .overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
  }

  .modal {
    background: #16213e;
    border: 2px solid #7cb3f0;
    border-radius: 8px;
    padding: 2rem;
    min-width: 300px;
    text-align: center;
  }

  .modal h3 {
    color: #7cb3f0;
    margin-top: 0;
  }

  .message {
    margin-top: 0.5rem;
    padding: 0.5rem;
    background: rgba(255, 215, 0, 0.2);
    border-radius: 4px;
    color: #ffd700;
  }
</style>

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. Which method in the object returned from an action responds to parameter changes?

Useful articles