CookieEater
CookieEater

Reputation: 2506

Svelte - Prevent re-rendering when updating a value

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>

Upvotes: 2

Views: 2344

Answers (2)

Siva Kondapi Venkata
Siva Kondapi Venkata

Reputation: 11011

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>

Upvotes: 0

CookieEater
CookieEater

Reputation: 2506

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.

Upvotes: 1

Related Questions