zodern / melte

Svelte compiler for Meteor with built in tracker integration and HMR
MIT License
33 stars 14 forks source link

nested $m does not unsubscribe #28

Closed tosinek closed 1 year ago

tosinek commented 1 year ago

Because of SSR, I am guarding subscription calls with Meteor.isClient, otherwise the SSR-generated page would fail because subscribe is not available on the server. But in such case, it looks like it won't unsubscribe on dismount.

if (Meteor.isClient) {
  $m: Meteor.subscribe('zodern.does.great.job')
}

I can do it manually though


  let subHandle: Meteor.SubscriptionHandle | undefined = undefined
  if (Meteor.isClient) {
    $m: subHandle = Meteor.subscribe('zodern.does.great.job')
  }

  onDestroy(() => {
    if (Meteor.isClient) {
      subHandle?.stop()
    }
  })
zodern commented 1 year ago

@tosinek do you know if normal reactive statements ($:) work when nested? $m: statements are rewritten into $: reactive statements. If reactive statements are supported when nested, then we can update melte to support them also.

One way to work around this is by writing it as

$m: Meteor.isClient && Meteor.subscribe('zodern.does.great.job')

or

$m: {
  if (Meteor.isClient) {
    Meteor.subscribe('zodern.does.great.job')
  }
}
ceigey commented 1 year ago

@tosinek do you know if normal reactive statements ($:) work when nested?

Howdy, I'm a random lurker. I remember seeing this when revisiting the Svelte Tutorial recently. See Reactive Statements. As you can see that example has $: in the top level of the <script /> tag.

The documentation supports this elsewhere:

Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the $: JS label syntax. Reactive statements run after other script code and before the component markup is rendered, whenever the values that they depend on have changed.

Based on that tutorial, the following would be expected:

$m: if (Meteor.isClient) {
  Meteor.subscribe('zodern.does.great.job');
}

I guess where there might be some style mismatch is that if (Meteor.isClient) is often used at the top level*. But Svelte requires $: at the top level. So probably Svelte should win out here, because if (Meteor.isClient) can still occur in a nested context.

*for things like conditional imports etc which won't fly in an ESM world without conditional compilation or using require behind the scenes...

tosinek commented 1 year ago

Thank you both, I was too tired to figure out that swintching it the other way round solves the issue. So I guess this can be closed as $m: Meteor.isClient && Meteor.subscribe('zodern.does.great.job') works well.