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

Svelte 5 #31

Open
jamauro opened this issue Dec 3, 2023 · 5 comments
Open

Svelte 5 #31

jamauro opened this issue Dec 3, 2023 · 5 comments

Comments

@jamauro
Copy link
Contributor

jamauro commented Dec 3, 2023

Thanks for making this package!

Any preliminary thoughts on support for Svelte 5? My guess is that it won't release until early next year but the fine grained reactivity by default with proxies looks pretty good: sveltejs/svelte#9739

I'm not entirely sure how that plays with Meteor's reactive cursors though. Was wondering if you've already given this some thought.

@jamauro
Copy link
Contributor Author

jamauro commented Mar 14, 2024

@zodern I think something like this might work. What do you think?

// tracker.svelte.js inside zodern:melte
import { Tracker } from 'meteor/tracker';
import { onDestroy } from 'svelte';

export const track = (reactive) => { // reactive is a reactive data source, e.g. a cursor or a value like Meteor.user()
  const isCursor = reactive instanceof Meteor.Collection.Cursor;
  let data = isCursor ? $state([]) : $state(undefined);
  let handle;

  if (isCursor) { // allows for fine-grained updates
    handle = reactive.observe({
      added: (document) => data.push(document),
      changed: (newDocument, oldDocument) => data[data.findIndex((item) => item._id === oldDocument._id)] = newDocument,
      removed: (oldDocument) => data.splice(data.findIndex((item) => item._id === oldDocument._id), 1)
    });
  } else {
    handle = Tracker.autorun(() => {
      data = reactive
    })
  }
   
  onDestroy(() => handle.stop());

  return data;
};

export const subscribe = (subscriptionName, ...args) => {
  let sub = $state({ ready: false })

  const handle = Meteor.subscribe(subscriptionName, …args, onReady(() => {
    sub.ready = true
  });
 
  onDestroy(() => handle.stop());

  return sub;
};
// store.js
import { track } from 'meteor/zodern:melte'

export const currentUser = track(Meteor.user())
// App.svelte
 <script>
  import { track, subscribe } from 'meteor/zodern:melte'

  const sub = subscribe('todos');
  const todos = track(Todos.find());

  async function createTodo(event) {
    event.preventDefault();
    // call your Meteor method
  }
</script>

{#if !sub.ready}
  <p>loading…</p>
{/if}

{#if currentUser}
  <form onsubmit={createTodo}>
    <input type=‘text’ placeholder=‘Type to add new todos’ />
  </form>
{/if}

{#each todos as todo (todo._id)}
  <p>{todo.text}</p>
{/each}

I haven’t tried it yet so there might be issues with the above. When I attempted previously, I wasn’t able to get Svelte and Meteor 3 to play nicely together.

Maybe there’s an even better way to do it but this feels pretty nice given the direction Svelte 5 is taking.

@zodern
Copy link
Owner

zodern commented Mar 14, 2024

We'll want a solution that allows the reactive code to re-run, for example if the Todos query needs to change depending on another variable.

I was considering adding a $tracker method, and having the compiler rewrite it into svelte 5 code like we currently do for $m: statements. One challenge is svelte 5 has 3 different api's for reactive code that run code at different times ($derived, $effect, $effect.pre), and I currently am not sure which ones we need a tracker equivalent for.

@jamauro
Copy link
Contributor Author

jamauro commented Mar 15, 2024

We’ll want a solution that allows the reactive code to re-run

Ah yes, good point. Will do some more thinking here.

I was considering adding a $tracker method

Nice! That could be really nice if it was treated like the other runes in that it wouldn’t need to be imported.

One challenge is svelte 5 has 3 different api's for reactive code that run code at different times ($derived, $effect, $effect.pre), and I currently am not sure which ones we need a tracker equivalent for.

Yeah my understanding is that $: got split into $derived and $effect. $effect.pre is akin to beforeUpdate.

@camstuart
Copy link

Looking forward to see how this goes! +1

@Raphael-Bahuau
Copy link

Hello, any news :D ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants