Comments (8)
It means we're going to look into the issue, not that the request is accepted per say :)
from svelte.
We really want to avoid adding more runes here where possible. If possible, bindings should preferably be transparent and not something you need to worry about. So there's likely an alternative approach to dealing with this.
from svelte.
What's the advantage of doing this instead of just doing
<!-- MyComponent.svelte -->
<script>
let { values = $bindable(), onChange } = $props();
const addValue = (newValue) => {
values ||= [];
values.push(newValue);
onChange?.(values);
};
</script>
....
<!-- Somewhere -->
<MyComponent bind:values={...}>
<!-- Somewhere else -->
<MyComponent values={...} onChange{...}>
this way you also avoid creating new memory by spreading.
from svelte.
What's the advantage of doing this instead of just doing
<!-- MyComponent.svelte --> <script> let { values = $bindable(), onChange } = $props(); const addValue = (newValue) => { values ||= []; values.push(newValue); onChange?.(values); }; </script> .... <!-- Somewhere --> <MyComponent bind:values={...}> <!-- Somewhere else --> <MyComponent values={...} onChange{...}>this way you also avoid creating new memory by spreading.
You can test it out, it triggers a warning and it has side effect. It shouldn't update values because I didn't use bind. To get rid of this error, I would be forced to create a "memory spreading" as you call it to avoid that side effect
"%c[svelte] ownership_invalid_mutation\n%cMyComponent.svelte
mutated a value owned by App.svelte. This is strongly discouraged. Consider
passing values to child components with `bind:`, or use a callback instead"
from svelte.
How about something like:
let { prop = $bindable.required() }
Maybe a different name like $bindable.must
, or even, $bound
and $bound.optional
. This would be a pretty massive breaking change, but the way I see it optional bindings shouldn't be allowed at all unless there is a way for the child to know when the value is bound to or not (which adds unnecessary complexity).
If there is state to be shared from the child to the parent, I believe there are 2 options for the parent:
- the parent does not provide the prop at all. The child is independent and manages its own state.
- the parent binds to the prop, gaining "ownership" of the value (the child still controls/owns it, but from a logic standpoint it's as if the parent provides it and changes it based on callbacks from the child).
Child components will want to implement one or both of these behaviours:
- be fully-controlled by a parent
- manage their own state
If only one of the behaviours is needed, either a callback function (events) or bindable prop with no default is used. If you need both, use a bindable prop with a default value.
The problem is, as a child component, if you have a bindable prop, you will mutate it, otherwise it wouldn't be bindable. I believe the warning doesn't really make sense and might not catch potential issues fast enough (parent doesn't bind the prop but the child rarely mutates it so the warning never pops up). I think there are a few solutions to this:
- Add a way to make bindings required
- Make all bindings required (it's okay to omit the prop completely if it has a default value) - breaking
- Add a way for child components to tell which props are bound to (difficult to use by component authors - should they always check before mutating props?)
Whatever you thoughts on everything I said here are, my only question is: what is the use case for allowing prop={var}
(without bind:
) on $bindable
props? If there is a valid use case, how should the warning in the original question be fixed?
from svelte.
How about something like:
let { prop = $bindable.required() }Maybe a different name like
$bindable.must
, or even,$bound
and$bound.optional
. This would be a pretty massive breaking change, but the way I see it optional bindings shouldn't be allowed at all unless there is a way for the child to know when the value is bound to or not (which adds unnecessary complexity). If there is state to be shared from the child to the parent, I believe there are 2 options for the parent:
- the parent does not provide the prop at all. The child is independent and manages its own state.
- the parent binds to the prop, gaining "ownership" of the value (the child still controls/owns it, but from a logic standpoint it's as if the parent provides it and changes it based on callbacks from the child).
Child components will want to implement one or both of these behaviours:
- be fully-controlled by a parent
- manage their own state
If only one of the behaviours is needed, either a callback function (events) or bindable prop with no default is used. If you need both, use a bindable prop with a default value.
The problem is, as a child component, if you have a bindable prop, you will mutate it, otherwise it wouldn't be bindable. I believe the warning doesn't really make sense and might not catch potential issues fast enough (parent doesn't bind the prop but the child rarely mutates it so the warning never pops up). I think there are a few solutions to this:
- Add a way to make bindings required
- Make all bindings required (it's okay to omit the prop completely if it has a default value) - breaking
- Add a way for child components to tell which props are bound to (difficult to use by component authors - should they always check before mutating props?)
Whatever you thoughts on everything I said here are, my only question is: what is the use case for allowing
prop={var}
(withoutbind:
) on$bindable
props? If there is a valid use case, how should the warning in the original question be fixed?
Hi,
These are indeed very good suggestions! However, I'm on the fence of disagreement that a bindable prop should always be binded. I believe the very best case scenario should be
- $bindable() -> optional binding by default
- $bindable.must() -> mandatory binding (I leave the syntax choice to Svelte maintainers)
- $isBinded(prop) -> Tell if a prop is binded or not (I leave the syntax choice to Svelte maintainers)
The reason is that I believe it should be possible to have a component that can either manage its own state or manage an external state with bind.
Let's take an exemple of a "Svelte Select Library" named "MySelect"
// Component mutates and always display the current selection based on value prop
<MySelect bind:value={value} options={...}>
// Component uses its own state to manage the value. When the form is submitted, it will be submitted like a normal form input.
<MySelect name="user[firstName]" options={...}>
// Component uses its own state to manage the value. A callback onChange is used to do something with the selected value
<MySelect value={initialValue} options={...} onChange={/* do something */}>
from svelte.
@trueadm If this just got added to the milestone 5.0, does this mean it's considered as an "accepted" request? I was wondering what could be done to drag more attention into this as I believe this is kind of important in some case scenario
from svelte.
It means we're going to look into the issue, not that the request is accepted per say :)
Understood thanks! By the way I would love to have your opinion on #11672 (comment) above
from svelte.
Related Issues (20)
- Improve message for error "Nesting selectors can only be used inside a rule" HOT 5
- Svelte 5: Regression since 5.0.0-next.162 with #each or render HOT 2
- Svelte v4 components under Svelte v5: Internals leaked through slot variables when defined in component HOT 7
- Svelte 5 - Relax Variable Naming Restrictions on $-Prefixed Variables HOT 7
- Svelte 5: Components in #if blocks don't trigger their $effect rune HOT 9
- False positive error: rune outside svelte HOT 1
- Bump all dependencies before final release
- Documentation Clarification for Rookies HOT 3
- Svelte 5 (5.0.0-next.167): Upgrading to the latest Svelte 5 breaks SvelteKit routing HOT 9
- Svelte 5: this type of directive is not valid on components HOT 5
- [Svelte 5] `{#if}` block with several reactive children does not re-render properly HOT 12
- Svelte 5 legacy: transition not conveyed using $$restProps and svelte:element HOT 1
- next.167 breaks <svelte:component> in development mode
- Sveltekit + Svelte 5: Navigating only loads the layout, not the page HOT 2
- Svelte 5: Mutating data in load fn stops page reactivity HOT 4
- Svelte 5: this type of directive is not valid on components HOT 4
- Svelte 5: Inaccurate Error Message HOT 1
- `batch` function to update multiple sources at once HOT 4
- Svelte 5 reporting invalid type error on Svelte 4 component using slot
- Make aria- dependencies optional HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from svelte.