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

Can't use destructuring assignment to get 2 stores from object, when variables declared with let #5388

Closed
TylerRick opened this issue Sep 11, 2020 · 2 comments · Fixed by #5390
Labels

Comments

@TylerRick
Copy link

TylerRick commented Sep 11, 2020

Describe the bug

When using object destructuring assignment to extract 2 stores out of an object, like this:

let store1
let store2
({
	store1,
	store2,
} = context);

, then only whichever store is assigned to a variable first (in this case store1) can be used. The other one is undefined when you (auto)subscribe to it ($store2).

To Reproduce

I have tried many variations to try to identify which factors are necessary and sufficient conditions for this strange behavior to occur. The 1 broken behavior and various variations that seem to work fine are summarized in this REPL repro.

It appears that this strange behavior — $store2 being undefined (see Broken.svelte) — only occurs iff all of these conditions are true:

  1. We use destructuring assignment instead of regular assignment (see AssignWithoutDestructure1.svelte)
  2. Reference $store1 at all (see OnlyReferenceStore2.svelte)
  3. Use let instead of const (see Const.svelte)
  4. Destructure/assign store1 first (see AssignStore2First.svelte)

Why exactly can I not use this combination of factors in my Svelte component? What is the rule that I am breaking, and where is it documented?

Expected behavior

I expect to be able to use let and destructuring assignment with store objects just the same as I can with any other type of value.

This works just fine, for example:

let store1
let store2
({
	store1,
	store2,
} = {store1: 'value1', store2: 'value2'});

// store1 => "value1"
// store2 => "value2"

so I don't think there's anything wrong with my JavaScript. So what is so special about stores as values that would make it not work? And why does let vs. const make a difference here? Is the Svelte compiler doing something special with lets (even though I'm not using $: here) that is causing this strange behavior?

Severity

It seems medium severe to me. I can probably work around it (I will attempt that next), but it certainly diminishes my confidence in Svelte when:

  1. a Svelte store mysteriously reports being undefined for no apparent reason
  2. something that seems like standard JavaScript just doesn't work as expected and I have to come up with an arbitrarily different way to write it

Maybe I'm just doing something wrong, but I couldn't figure it out (after hours of turning this into a simple as possible repro), so I reported this as a bug until proven otherwise... :)

@Conduitry
Copy link
Member

In the first broken example, the compiler is outputting

	let store1;
	$$subscribe_store1();
	let store2;
	$$subscribe_store2();
	$$subscribe_store1({ store1, store2 } = context);

which is incorrect - as opposed to the example without destructuring, where it is outputting

	let store1;
	$$subscribe_store1();
	let store2;
	$$subscribe_store2();
	$$subscribe_store1(store1 = context.store1);
	$$subscribe_store2(store2 = context.store2);

We need to make sure both subscription functions are called after the destructuring assignment happens. So we can continue to use the destructuring in the output, probably what makes them most sense is to make two separate subscription calls afterwards.

@Conduitry
Copy link
Member

This is fixed in 3.25.1 - https://svelte.dev/repl/ba980bfbd031448b8f49500f5900f305?version=3.25.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.

3 participants