Skip to content

Svelte bind:this does not give proper working inside onMount body #6919

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Ultarius opened this issue Nov 11, 2021 · 6 comments · Fixed by #6920
Closed

Svelte bind:this does not give proper working inside onMount body #6919

Ultarius opened this issue Nov 11, 2021 · 6 comments · Fixed by #6920

Comments

@Ultarius
Copy link

Ultarius commented Nov 11, 2021

Describe the bug

After importing Svelte component manually, there are issues retrieving the HTML element with the 'bind:this' binding. After using it inside the onMount function body, the page should be fully loaded and the value 'should' be available. After using a setTimeout block, the issue seems to be resolved.

Issue found after using svelte extension; https://github.com/ANovokmet/svelte-gantt

Seems broken from version=3.18.2

Reproduction

https://svelte.dev/repl/43c5c3945d354cfc8fffeb80f4099255?version=3.44.1

image

Logs

No response

System Info

https://svelte.dev/repl 

version=3.44.1

'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'

Severity

annoyance

@rmunn
Copy link
Contributor

rmunn commented Nov 12, 2021

The bind:this docs certainly do suggest that it should be available by the time onMount() runs, as that's precisely the scenario used in the docs example. Good repro REPL, thanks. It let me confirm that version 3.18.1 is the last version that worked, and that version 3.18.2 does not work. Also, there is no difference in the compiled output of your REPL between 3.18.1 and 3.18.2, so it's probably a difference in the runtime that caused this bug.

@rmunn
Copy link
Contributor

rmunn commented Nov 12, 2021

Interesting. If I change your REPL reproduction to mount the component like <Window /> instead of using new Window({ target: whatever }), then the bug does not occur. So it's got something to do with the timing of component creation with new vs when components are created via the "normal" process.

@rmunn
Copy link
Contributor

rmunn commented Nov 12, 2021

The cause appears to have been #4356, first released in version 3.18.2. I made a local reproduction, and built a custom Svelte package using a local checkout of the Svelte repro. I made only one change to my custo Svelte package, reverting the changes to flush() made in #4356, and that fixed the bug.

We'll probably need to add a regression test that exercises this scenario: creating a component via onMount(() = { new Component({target: whatever}); } and having that component do bind:this. That was a scenario that #4356 broke, but no unit tests exercised that scenario at the time so the breakage wasn't noticed.

@RaiVaibhav
Copy link
Contributor

It's related to #6760

@roblevintennis
Copy link

roblevintennis commented Nov 29, 2021

I have a tab component that works in Storybook, but recently I added a test app and my bind:this array of refs are undefined even after mounting, and until I actually click on one of the tabs.

This is needed to be able to do accessibility keyboard navigation and control focus properly.

Here's the repo https://github.com/AgnosticUI/agnosticui and the working storybook will run with yarn && yarn start:svelte. The example app will require cd agnostic-svelte/examples; npm install && npm run start;.

I notice at runtime, that the working Storybook version gets into the callback below (but the one that isn't working doesn't get into it until I've clicked on a tab):

image

Sorry in advance that I don't have a small test case but I can't seem to repo it in small repl tests ¯_(ツ)_/¯

I can show the tab component's loop although it's a bit complex too as it provide a means for dynamic projection:

    {#each tabs as tab, i}
      {#if tab.tabButtonComponent}
        <svelte:component
...
        </svelte:component>
      {:else}
        <button
          bind:this="{tabButtonRefs[i]}" <---- this is just [] onMount
          on:click="{() => selectTab(i)}"
          on:keydown="{(e) => handleKeyDown(e, i)}"
          disabled="{isDisabled || disabledOptions.includes(tab.title) || undefined}"
          class="{tabButtonClasses(tab)}"
          role="tab"
          aria-controls="{tab.ariaControls}"
          tabindex="{tab.isActive ? '0' : '-1'}"
          aria-selected="{tab.isActive}"
        >
          {tab.title}
        </button>
      {/if}
    {/each}

Code is here: https://github.com/AgnosticUI/agnosticui/blob/master/agnostic-svelte/src/stories/Tabs.svelte#L354

I'm basically calling that with:

<script>
  import {Tabs } from 'agnostic-svelte';
  import Tab1 from "../../src/stories/TabPanel1.svelte"; // just simple html only components for panels
  import Tab2 from "../../src/stories/TabPanel2.svelte";
</script>
<Tabs size="large" tabs={[
  {
    title: "Tab 1",
    ariaControls: "panel-1",
    tabPanelComponent: Tab1,
  },
  {
    title: "Tab 2",
    ariaControls: "panel-2",
    tabPanelComponent: Tab2,
  },
]}></Tabs>

@Conduitry
Copy link
Member

This appears to have been a duplicate of #6760 and should be fixed in 3.44.3 - https://svelte.dev/repl/43c5c3945d354cfc8fffeb80f4099255?version=3.44.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants