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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spreading $$props to nested Child triggers reactive 'props' statement in every nested Child inside every Parent instance #4993

Closed
vatro opened this issue Jun 8, 2020 · 5 comments · Fixed by #5123
Labels

Comments

@vatro
Copy link

vatro commented Jun 8, 2020

Having multiple Parent.svelte components with a nested Child.svelte component and passing all props to Child by spreading Parent's '$$props' to it: changing props on one Parent instance will trigger reactive 'props' statements of every nested Child inside every Parent instance.

Here is the REPL demonstrating the issue (incl. working / not working as expected code): https://svelte.dev/repl/c7948002ddec40aea93d1447d0fc9aa9?version=3.23.0

Expected behavior:
Changing props on one Parent triggers only reactive 'props' statement of it's Child, not also of all other Parent instances.

I've asked a question on the Svelte discord 'support' server and got this useful responses:
https://discord.com/channels/457912077277855764/506988048375087114/719672553291120790
https://discord.com/channels/457912077277855764/506988048375087114/719678060680577029

Chrome 83.0.4103.61, Windows 10, Svelte 3.23.0, Rollup

The bug is not severe to me as there is a workaround (actually more common workflow) by just exporting all props in Parent and passing them one by one to Child (see REPL above).

Thanks!

@dimfeld
Copy link
Contributor

dimfeld commented Jun 9, 2020

The issue here is that in the REPLs top-level component's update (p) function, it calls $set even if there are no changes:

const parent0_changes = {};
if (dirty & /*props1*/ 1) parent0_changes.props = /*props1*/ ctx[0];
parent0.$set(parent0_changes);

And then in the Parent component which uses a $$props spread in its template, the $set function always invalidates $$props even if the incoming props object is empty:

$$self.$set = $$new_props => {
  $$invalidate(0, $$props = assign(assign({}, $$props), exclude_internal_props($$new_props)));
};

So these two combine to make situation where any time something changes in the top-level component, all of its components go through state invalidation.

IMO the obvious fixes would be one or both of these:

  1. Check the changes object in the update function and don't call $set if it's empty.
  2. $set inside a component that uses $$props should check if $$new_props actually has any keys.

Someone more familiar with the Svelte internals may have a better idea though.

@vatro
Copy link
Author

vatro commented Jun 9, 2020

The issue here is that in the REPLs top-level component's update (p) function, it calls $set even if there are no changes:

☝️ but the issue is not limited to REPL, I stumbled over it locally (Svelte 3.23.0) and then tried to test it more isolated on REPL.

@dimfeld
Copy link
Contributor

dimfeld commented Jun 9, 2020 via email

@vatro
Copy link
Author

vatro commented Jun 9, 2020

I was just referring to the example in the REPL and the code that was compiled from it, not the actual REPL component.

ah, ok, I misunderstood it, sorry. 😬

@Conduitry
Copy link
Member

Fixed in 3.24.1 - https://svelte.dev/repl/c7948002ddec40aea93d1447d0fc9aa9?version=3.24.1

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

Successfully merging a pull request may close this issue.

4 participants