Skip to content

$effect.pre doesn't work properly if created on mount. #16556

@HighFunctioningSociopathSH

Description

Describe the bug

$effect.pre runs late and after the DOM is updated if it's initialized in onMount or Actions or Attachments.

Reproduction

Take the following code,

<script lang="ts">
  let node = $state<HTMLDivElement>();
  let colors = $state(["red", "blue"]);
  $effect.pre(() => {
    if (!node) return;
    colors ;
    console.log("$effect.pre", Array.from(node.children));
  });
  $effect(() => {
    if (!node) return;
    colors ;
    console.log("$effect", Array.from(node.children));
  });
</script>

<button
  onclick={() => {
    colors = colors.toReversed();
  }}
>
  change
</button>

<div bind:this={node}>
  {#each colors as color, i (color)}
    <div id={color === 'blue' ? "blue" : ""}>
      {color}
    </div>
  {/each}
</div>

Whenever I change the colors array, the $effect.pre and $effect run properly since $effect.pre logs the children as they were before the change occurs, since it's supposed to run before the DOM updates.
But if you put those effects inside an onMount or an Action or Attachment, the $effect.pre also logs the same output as the $effect, and you miss the snapshot of the DOM before the change.

<script lang="ts">
  let node = $state<HTMLDivElement>();
  let colors = ["red", "blue"];
  onMount(() => {
    $effect.pre(() => {
      if (!node) return;
      array;
      console.log("$effect.pre", Array.from(node.children));
    });
    $effect(() => {
      if (!node) return;
      array;
      console.log("$effect", Array.from(node.children));
    });
  });
</script>

<button
  onclick={() => {
    colors = colors.toReversed();
  }}
>
  change
</button>

<div bind:this={node}>
  {#each colors as color, i (color)}
    <div>
      {color}
    </div>
  {/each}
</div>

This also doesn't work in the playground, so I can't provide a REPO, but it hints that maybe it has something to do with the $effect.pre not going through the server-side code, since putting it in onMount or using playground skips server-side analysis.

Logs

System Info

System:
    OS: Windows 11 10.0.26100
    CPU: (16) x64 12th Gen Intel(R) Core(TM) i7-12650H
    Memory: 6.32 GB / 15.63 GB
  Binaries:
    Node: 23.11.0 - C:\nvm4w\nodejs\node.EXE
    npm: 11.4.1 - C:\nvm4w\nodejs\npm.CMD
    pnpm: 10.13.1 - C:\nvm4w\nodejs\pnpm.CMD
  Browsers:
    Edge: Chromium (136.0.3240.64)
    Internet Explorer: 11.0.26100.1882

Severity

blocking all usage of svelte

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting submitterneeds a reproduction, or clarification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions