Skip to content

$effect runs before $effect.pre #16256

Open
Open
@gwwo

Description

@gwwo

Describe the bug

The parent's $effect runs before its $effect.pre, when the child component inserts a new input and shifts focus, which triggers expanded change in the parent.

<script>
  let expanded = $state(false);
  $effect(() => {
    expanded;
    console.log("run effect", expanded);
  });

  $effect.pre(() => {
    expanded;
    console.log("run pre-effect", expanded);
  });

  let inputBar;
  $effect(() => {
    if (expanded && inputBar) setTimeout(() => inputBar.focus(), 400);
  });

  import Component from "./Component.svelte";
</script>

{#if expanded}
  <input
    bind:this={inputBar}
    onblur={() => (expanded = false)}
    placeholder="input"
  />
  <Component></Component>
{:else}
  <button onclick={() => (expanded = true)}>expand</button>
{/if}

Component.svelte

<script>
  let showAnother = $state(false);
  let anotherInput;

  $effect(() => {
    if (showAnother && anotherInput) anotherInput.focus();
  });
</script>

<button
  onmousedown={
    (e) => e.preventDefault()
  } 
  onclick={() => showAnother = true}> show another input and switch focus
</button>

{#if showAnother}
  <input bind:this={anotherInput} placeholder="another input" />
{/if}

Reproduction

https://svelte.dev/playground/c60f01e426f642f7a06629fc0fbf6e22?version=5.34.8

Logs

Image

System Info

playground

Severity

annoyance

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions