Svelte - Prevent re-rendering when updating a value

Viewed 630

I'm doing a CSS-based custom animation as shown below, but I do not want to animate on the initial render. At first, I thought I could easily achieve this creating a new flag that gets set on mount. However, I'm not sure how I can achieve this because all variables I create at the top level will cause re-render when it's updated.

I read that anything declared at the top level will cause re-rendering on assignments. So, I'm forced to create this flag inside a function, but doing so doesn't let me access the variable in HTML. How can I achieve this?

    <script lang="ts">
      import { onMount } from 'svelte';
      import classnames from 'classnames';

      let element: HTMLDivElement;
      let mounted = false;

      onMount(() => {
        const animationEndHandler = () => {
          element.classList.remove(animation);
        };
        element.addEventListener('animationend', animationEndHandler);

        mounted = true; // This needs to not cause re-rendering.

        return () => {
          element.removeEventListener('animationend', animationEndHandler);
        };
      });

      export let animate: boolean;
      export let animation: string;
    </script>

    <div
      class={classnames('animated', { [animation]: animate && mounted })} // <== This attaches the variable `animation` when `animate && mounted` is true.
      bind:this={element}
    >
      <slot />
    </div>
2 Answers

I solved it by creating an integer counter and validate that it's greater than 0. This is ugly, but I can't find any other ways.

Instead of using class directive on element, if you add the 'class' in the onMount, should work right? (only thing, we need additionally to add the css animation class name(s) to :global() scope, as svelte might remove unused css classes).

<script>
    onMount(() => {
        const animationEndHandler = () => {
            element.classList.remove(animation);
        };
        element.addEventListener('animationend', animationEndHandler);

        element.classList.add(animation);

        return () => {
            element.removeEventListener('animationend', animationEndHandler);
        };
    });
</script>
Related