Closed sphinxc0re closed 2 months ago
It's the Svelte 5 component's responsibility to pass a non-proxied object to any external code that can't deal with proxies - whether that data is passed directly or indirectly. In the Svelte 5 component, you could do something like <Other data={$state.snapshot(data)} />
.
Since you already have compute
in a separate file you can make it a svelte.js
file and use runes there.
This fixes your problem and you could even have a file that just does export an unstate
function that calls $state.snapshot
....i do wonder if such a function could be exported as an utility from svelte itself tho.
It's the Svelte 5 component's responsibility to pass a non-proxied object to any external code that can't deal with proxies - whether that data is passed directly or indirectly. In the Svelte 5 component, you could do something like
<Other data={$state.snapshot(data)} />
.
This is not entirely true tho since maybe you need the data to be reactive in the svelte 4 component and then the component may need to pass it to something that doesn't deal with proxies. But as i've commented above is technically still doable by extracting the function to a svelte.js
file
The property should still be set on every change to data
and in Svelte 4 components the reactivity is not based on proxies. I think this should just work.
Okay, I made another reproduction that might illustrate my problem a little better.
https://github.com/sphinxc0re/testing-svelte-5-bug
With this, it should be clear, that while I'm in Svelte 5 (runes) country when mounting the component, I have no choice but to pass in a full $state(...)
object to keep reactivity even when rendering a Svelte 4 (no runes) component
So your problem is that you want to mount something and update the component from outside? In that case I suggest to use createClassComponent(..)
from svelte/legacy
, which doesn't require you to use $state
and doesn't create a proxy for the object.
Okay, I made another reproduction that might illustrate my problem a little better.
https://github.com/sphinxc0re/testing-svelte-5-bug
With this, it should be clear, that while I'm in Svelte 5 (runes) country when mounting the component, I have no choice but to pass in a full
$state(...)
object to keep reactivity even when rendering a Svelte 4 (no runes) component
Did you see my comment? You can make complexComputing.js
into complexComputing.svelte.js
and use $state.snapshot
there...and you can call that function from a svelte 4 component perfectly fine.
@dummdidumm We actually thought about using this function, but we also thought it might be wiser not to use it in case it gets dropped in a future version of Svelte. Our specific problem is not only do we have a ton of components, but we also use the component API a lot. Are you suggesting createClassComponent
is a valid start to a migration strategy?
@paoloricciuti I did see your comment, but unfortunately this is not an option 😞
@paoloricciuti I did see your comment, but unfortunately this is not an option 😞
Why?
@paoloricciuti It's out of my control. The code has to work as-is 🤷🏼♂️
@sphinxc0re createClassComponent
will be dropped when Svelte 4 syntax is dropped entirely, at which point you could not use your old components anyway. So yes, it's a valid migration strategy to use it in places where you run into problems like this.
Describe the bug
The boundary between Svelte 5 and a Svelte 4 components is unclear to me. In the reproduction below, I'm outlining this problem.
A Svelte 5 component in runes mode embeds a Svelte 4 component that doesn't have the tooling to work with runes (e.g.
$state.snapshot
). When the inner Svelte 4 component calls an external function, my expectation is, that this function receives a POJO. This would actually be my expectation regardless of what version the different Svelte components have.In the reproduction below, the external function uses a
structuredClone
, which then crashes due to the input data being aProxy
objectReproduction
https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAA5WRwW6DMAyGX8WKKrVIFdwprUShh-6wHnYsPTAwKxUkKAnbKsS7zyG0bJ00aYdItuM4__e7Y0VZoWL-sWM8rZH5LGwatmT62phEvWOlkXIlWpmZSqAyWTZ6k_BEl3UjpIaDPqOEQooa5q43ZK59OKcu6ssEVxryVKewhpnSqcZFB0rUqM8lf_PhmLAwDBO2hIRtt1sbRFFkgziObbDb7RJ2gt5JeOBNOnhgFXTmhx68oUaaa5GXRYk587VssV_eETNRN61GOXFe1HdG_By4rOyxmZQv7AcOrDfQGS7Pg_28hlwQxIQDpAWXsAf1gamc-LNKcMxj64IiSZluJeaRKS_MZGdl7ZJIF_xbP9X7v4kGA_65tm4k6--ru_niXpTZnDZn9KJCu8BR4syH11QSx9PL4dklGOIui-sPDOophKCecezNvtXD9ihtJG66h1H01ukDz1z9Jj_1X-hi_ou6AgAA
EDIT: Okay, I made another reproduction that might illustrate my problem a little better.
https://github.com/sphinxc0re/testing-svelte-5-bug
With this, it should be clear, that while I'm in Svelte 5 (runes) country when mounting the component, I have no choice but to pass in a full
$state(...)
object to keep reactivity even when rendering a Svelte 4 (no runes) componentLogs
No response
System Info
Severity
blocking an upgrade