sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.21k stars 4.09k forks source link

Svelte5: .focus() within $effect() does not work on initial load with ssr = false #11182

Closed henrikvilhelmberglund closed 4 months ago

henrikvilhelmberglund commented 5 months ago

Describe the bug

I have an $effect() in a button component that focuses the first button in a div using a query selector. It works with SSR enabled but with SSR disabled the button isn't focused on initial load, but focuses when HMR kicks in when editing a file.

It also works when adding a 0 ms timeout in the $effect().

I could be doing something stupid but it could also be a bug.

Reproduction

https://stackblitz.com/github/henrikvilhelmberglund/svelte5-focus-bug?file=src%2Froutes%2F%2Bpage.js,src%2Fcomponents%2FMyButton.svelte,src%2Froutes%2F%2Bpage.svelte

Logs

No response

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (8) x64 Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz
    Memory: 2.99 GB / 15.95 GB
  Binaries:
    Node: 18.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.6.3 - ~\AppData\Roaming\npm\pnpm.CMD
    bun: 1.1.3 - ~\.bun\bin\bun.EXE
  Browsers:
    Edge: Chromium (123.0.2420.97)
    Internet Explorer: 11.0.19041.3636
  npmPackages:
    svelte: ^5.0.0-next.104 => 5.0.0-next.104

Severity

annoyance

trueadm commented 4 months ago

If you add this, you can find out what is stealing away focus from the button after it gets it:

document.querySelector("button").addEventListener('blur', () => {
  debugger
})

As you can see, it's SvelteKit trying to restore the focus. So in this case, the best advice is to instead handle the focus inside a microtask so your logic can happen after SvelteKit:

queueMicrotask(() => {
  document.querySelector("button").focus();
})

Hope that helps!