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

Reassigning $$props to another variable and using the spread operator casues issues with input's #5118

Closed
d0x2f opened this issue Jul 9, 2020 · 5 comments · Fixed by #5123
Labels

Comments

@d0x2f
Copy link

d0x2f commented Jul 9, 2020

Describe the bug
If you reassign $$props to another variable and use it with the spread operator on two or more inputs, typing into one clears the value from the other.
Only the displayed value is cleared, any bound variables retain the correct value.

To Reproduce
https://svelte.dev/repl/59246207fcc949b1b5691b045d3bbd7e?version=3.24.0

Type something in each input box and observe the behaviour for the top two.
Typing in one clears the other.

Expected behavior
Previously to v3.24.0, it was possible to use $$props this way without any issue.

Information about your Svelte project:
Firefox 79b, Arch Linux, Svelte 3.24.0, rollup

Severity
This isn't a blocker as such because, depending on the specific case, a workaround ought to be easy to find.
However it's exhibited in a dependency of my project in which I can't readily implement a work around.
Namely sveltestrap (issue bestguy/sveltestrap#157).

@tanhauhau
Copy link
Member

Yes, it is a bug.

And also, using const props = $$props, the props will always remain as the initial $$props of the component. it will not be reactive, unless

$: props = $$props;

Secondly, $$props will contain value, which you already bind it again. if you want to spread remaining props that is not declared, you can use $$restProps.

@lukasmoellerch
Copy link
Contributor

It seems like this happens because you effectively assign the value of the value attribute of the input element twice: The first time because value is passed as a prop due to the binding in the parent component and the second time value is assigned as a result of the bind:value of the input element. That means that your example is similar to the following:

<script>
	export let value;
	let something = {value: "12"};
</script>
<button on:click={() => something.value++}>Increment</button>
<input {...something} type="text" bind:value />

In this example the value of the input element is also assigned twice: Because it is part of the spread {...something} and also because a binding is specified. The Component2 works because the two assignments always match up because the $$props is reactive and will update automatically, but const props = $$props will not update and will thus always be {value: ""}. When the parent component updates Component1 will trigger a spread update and reassign value resulting in the value being set to "" again. Currently the generated code calls component0.$set(component0_changes); also if component0_changes is empty.

We could potentially add an additional check around https://github.com/sveltejs/svelte/blob/master/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts#L518 so that $set is only called if there is at least one change in ${name_changes}.

@lukasmoellerch
Copy link
Contributor

lukasmoellerch commented Jul 10, 2020

@tanhauhau What's the exact semantic if an attribute is assigned twice? Is that undefined behavior or is it supposed to be the value that was assigned last? Could we maybe add a warning if a spread contains a key that is already set on that element?

@tanhauhau
Copy link
Member

We could potentially add an additional check around https://github.com/sveltejs/svelte/blob/master/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts#L518 so that $set is only called if there is at least one change in ${name_changes}

yes, there's already an similar existing issue #4993

What's the exact semantic if an attribute is assigned twice? Is that undefined behavior or is it supposed to be the value that was assigned last?

I am not sure whether it is documented anywhere, so I dont have an official answer for this. but imo, the last assigned value should prevail.

@Conduitry
Copy link
Member

Fixed in 3.24.1 - https://svelte.dev/repl/59246207fcc949b1b5691b045d3bbd7e?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.

5 participants