svelte-meteor-data
svelte-meteor-data copied to clipboard
A reactive subscription creates infinite amount of subscriptions when props change
When I create a subscription that reacts to changing props like so:
<script>
export let page;
$: Meteor.subscribe('stuff', { page });
</script>
...the old subscriptions will not be stopped until the component is destroyed. That means, if page changes a lot, a lot of "stale" subscriptions will be persisted until the component is destroyed.
Wouldn't it make sense to close the old subscription when the props change?
Yes, this is a known shortcoming. I have not found a clean way to address this yet. You'd need to do something like this:
let subscription;
$: {
if (subscription) subscription.stop();
subscription = Meteor.subscribe('stuff', { page });
}
The way to make this work out of the box would require hooking into the Svelte update call such that it stops all the current subscriptions on every update. However, the problem with that is that not every $: block is rerun on an update (only the ones for which dependencies changed), so we'd need to be selective about which subscriptions to stop, and we just don't have that information. The only way this would work is if we forced Svelte to re-run all of the $: lines on every single update, which would basically cripple performance.
So, I don't think this can be cleanly fixed without patching the Svelte compiler itself to create some kind of guard block that would let us do this.
The only other way I can think of addressing this would be to discourage Meteor.subscribe and instead create a separate store-based interface that would work something like this:
$: sub = subscribable('stuff', { page });
$: $sub
The syntax is a little weird and not intuitive though, with the way that the store needs to be explicitly instantiated like that.
Other thoughts are welcome.
Oh, I haven't tried it, but this actually might work today, without a specific subscribable store:
$: sub = useTracker(() => Meteor.subscribe('stuff', { page }));
$: $sub
Both of these suggestions seem to work, thank you! Had some trouble at first due to a forgotten {#await Meteor.subsribe(...} below the <script> block...
I prefer this approach
let subscription;
$: {
if (subscription) subscription.stop();
subscription = Meteor.subscribe('stuff', { page });
}
since it's obvious what's going on, the last example is...not.
Still, would be great to find a way to make it work out of the box! Have you tried asking for comments in the Svelte Discord channel?