Skip to content

Dimension bindings (clientHeight) not updated after {#await} block resolves. #4580

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
Leftium opened this issue Mar 20, 2020 · 5 comments
Closed

Comments

@Leftium
Copy link

Leftium commented Mar 20, 2020

Describe the bug

Dimension bindings (clientHeight) not updated after {#await} block resolves.

To Reproduce

Minimal example in REPL Only repros in REPL

New minimal example that repros outside REPL

  • Slightly modified from https://svelte.dev/tutorial/slots
  • The promise fires immediately. Depending on where you run it there are two behaviors:
    1. Outside REPL: clientHeight does not reflect actual height until <details> toggled.
    2. REPL: clientHeight does not change even if <details> toggled. This might be due to the sandbox.
    3. Modify https://svelte.dev/tutorial/slots: behaves like outside REPL.

Expected behavior

The dimension bindings should update after the {#await} block causes changes to the DOM.

Information about your Svelte project:

  • Chrome 80
  • Windows 10
  • Svelte 3.20.1
  • Rollup

Severity

  • Just cosmetic problems with my program.
  • I think I can find a work-around.

Additional context

I am making a sticky header component. Some elements are added after fetching data. This causes the sticky header to become sticky too early, causing some jumping and/or displaying parts of the non-sticky part before the sticky header (which should be totally scrolled out of view.)

@Conduitry
Copy link
Member

This example is working fine for me outside of the REPL, on Firefox and Chrome. See #2147. Do you have have a minimal repro of this happening that doesn't involve the REPL?

@Leftium
Copy link
Author

Leftium commented Mar 20, 2020

Indeed, the original example does not repro outside the REPL. I have updated the issue with a new example that does repro outside the REPL. The original example must be missing an interaction between component slots, {#await}, and bind:clientHeight.

What would be the best/simplest work-around to manually force bind:clientHeight to update? (preferably without visibly affecting the page)

@BillyLevin
Copy link
Contributor

I've spent some time looking at this issue, but can't seem to get to the crux of the problem. I'll write down some stuff I've looked at and hopefully someone smarter than me can figure it out (or point me in the right direction).

Here's a minimal example, not using slots: https://svelte.dev/repl/47047698dd5740d2a854d367e9c5629d?version=3.21.0

It looks like it could be some kind of race condition between the promise resolving and the div_elementresize_handler listener being attached here:

if (is_crossorigin()) {
iframe.src = `data:text/html,<script>onresize=function(){parent.postMessage(0,'*')}</script>`;
unsubscribe = listen(window, 'message', (event: MessageEvent) => {
if (event.source === iframe.contentWindow) fn();
});
} else {
iframe.src = 'about:blank';
iframe.onload = () => {
unsubscribe = listen(iframe.contentWindow, 'resize', fn);
};
}

If the promise is changed to something like this:

let promise = new Promise(res => {
    setTimeout(() => {
        res();
    }, 0)
});

Then in the REPL, it'll sometimes work, and sometimes won't, pretty randomly. On a local project it seems to work all of the time (you can see a small flicker as the value updates from 74 -> 95)

Not sure where to go from here

@zwergius
Copy link

I'm seeing similar issues with an {#if} block, using bind:clientHeight inside where it randomly updates with the correct height

@dummdidumm
Copy link
Member

Fixed in Svelte 5

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

No branches or pull requests

7 participants