Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

components render with outdated state when using let:* on slots #8052

Open
ivanhofer opened this issue Nov 23, 2022 · 1 comment
Open

components render with outdated state when using let:* on slots #8052

ivanhofer opened this issue Nov 23, 2022 · 1 comment

Comments

@ivanhofer
Copy link
Contributor

Describe the bug

I try to describe the example, but I think it is easier to take a look at the code 馃槄

I have a Wrapper component that provides a slot prop via let:x.
Inside the Wrapper component another "List" component is repsonsible for iterating over a list of items and adding new items to the list.
The "List" provides a default slot so the "Parent" can decide how he wants to render the item.

The problem I have is that, I can't bind directly to the item provided by the "List"s slot props. Therefore I need to use two-way binding and then directly access the item in the "Parent" component.

As soon as a new item gets added, the "List" and the "Parent" knows about it. So the newly added item will be renderd.
But the items were not yet updated inside the scope of the "List" where it tries to render it. So the code tries to access an element that should be there, but isn't because that scope uses an outdated state.

As soon as I remove let:x everything works fine.

Reproduction

Svelte REPL: https://svelte.dev/repl/1f1ee60fbd4a41b7942241f828589ed9?version=3.53.1

  1. click on the "add item" button
  2. open the console to see the error
  3. reload the page
  4. remove let:x from the Wrapper component
  5. click on the "add item" button
  6. it works now

I have logged the values of all variables from step 2:
image

In line 4 you can see that the values array already has two items but in line 5 items only contains a single item. It uses an older version of the state.

Logs

No response

System Info

Svelte REPL

Severity

annoyance

@berndfuhrmann
Copy link

We are facing a similar issue here. The provided REPL above already demonstrates it well.
I tried to debug my way through this problem. My hunch is that something here could be the culprit:

if (!block) {
block = create_each_block(key, child_ctx);
block.c();
} else if (dynamic) {
// defer updates until all the DOM shuffling is done
updates.push(() => block.p(child_ctx, dirty));
}

In line 45, create_each_block is called, which will in the REPL eventually call that console.log(4 with that faulty undefined value.
I'm new to the internals of Svelte, so I'd like to apologize in advance for not knowing how this should work.
The cited code snippet is in the update_keyed_each function here. This can be called from flush, inside that while loop:
update(component.$$);

At this point Svelte hasn't finished updating everything, so we're in a possibly invalid intermediate state. Is it ok to call user-provided code at this point? create_each_block does exactly that. I guess that user-provided code like that console.log would not expect to be called when the variables are in some intermediate state.
Would it make sense to defer that call to create_each_block until all the updates are through? I saw @tanhauhau already doing something in that direction. Would there be a good reason not to defer it?
Hope this helps!

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

No branches or pull requests

2 participants