I am currently rebuilding an app that was built in Blaze to Svelte, and WOW what a difference! I am working on pagination for a simple user list. Currently I just want to give users the ability to decide how many users to display at one time. It seems to work just fine when increasing in increments; however, I am seeing that when I go down in increments the number of users published does not change.
Here is how I am currently handling it…obviously Meteor/Svelte is super new…and I am sure there may be a better way:
Just trying to sort out how to update publications really. It seems like the afterUpdate method gets me 1/2 of the way there…but I am confused why after pushing a lesser number to the limit in Mongo it does not “re-subscribe” to the publication. I have been logging the “pageObj” in the publication and can verify that the data is being received properly.
However, that won’t work quite the way you might expect from a Tracker.autorun, because it will not automatically unsubscribe from the previous subscribe call, until the component is destroyed. (I have looked into making rdb:svelte-meteor-data handle this case, but this is not possible without instrumentation to the Svelte compiled output.)
You will need to do something like this instead, though I’m not 100% sure whether the circular dependency on subscription might cause a problem:
let subscription;
$: {
if (pageObj) {
subscription.stop();
subscription = Meteor.subscribe('AllUsersPaged', pageObj);
}
};
Finally, as a sidenote, my package automatically makes all cursors behave as Svelte stores, so you can simplify this code:
You should also bear in mind that the way you are passing the user object to SingleUserList will cause your entire user list to be rerendered whenever any one of them changes. The way to work around this is to either just pass in an identifier (having SingleUserList fetch the data on its own), give SingleUserList the immutable flag, or have the object be destructured by Svelte when passing it in.
Oh wow! Now this is a GREAT answer! Just as an FYI I got the idea of putting Meteor.subscribe inside of the Svelte callback from the current Svelte tutorial here on meteor.com. Not sure who we should tell about that…but being the fact that you wrote the package…I have a strong feeling I can take your word for it!
I am going to give all of this a try…but thank you for all of your development help to make the package in the first place! Dudes like you keep dudes like me excited about Meteor!!
Addendum: I just realised that by changing the useTracker in the last example I gave to a regular cursor, the call to Meteor.userId() will no longer be made reactively, so switching users would not automatically update the query. So ignore that suggestion unless the user cannot switch accounts while the component is active,
Are you saying this should be refactored to the following
$: Meteor.subscribe('tasks');
and it would have the same effect? when the component loads it will subscribe to the published data? and is that more inline with what you had in mind for your package?
One additional thing I might add…I was not able to get ready() to log true on the subscription. Also the subscription.stop() also did not have any impact, though the immutable idea seems to have worked.
I don’t recommend putting anything reactive inside a Svelte callback because the behaviour of Svelte inside them is not consistent (there are some pending issues and PRs regarding fixing the current behaviour).
If you put the Meteor.subscribe in the component (no $: prefix needed) scope, everything will work as it should, and the auto-unsubscribe will also take effect.
Ok cool thanks for the info, I am working on the React tutorial update at the moment and then I wanted to get the Angular tutorials up to date. so this might take me a minute to get on the top of my to do list but I will make that change as soon as i can
Hi! Here’s a helper function that I personally developped and use in my Svelte/Meteor projects.
import { Tracker } from "meteor/tracker";
import { onDestroy } from "svelte";
import { writable } from "svelte/store";
/* Store the result of a Meteor reactive function in a read-only store
* that exposes a `refresh` method to invalidate the computation.
* Could be used with Svelte reactive statements like so:
* $: store.refresh(...dependencies) */
export default function trackable(reactiveFn) {
const store = writable();
const computation = Tracker.autorun(() => store.set(reactiveFn()));
const { subscribe } = store;
onDestroy(() => computation && computation.stop());
return {
subscribe,
refresh: () => computation && computation.invalidate(),
};
}
In a nutshell, a trackable store exposes a refresh method that invalidates the computation. When used in a Svelte reactive statement, it then invalidates each time the dependencies change. To access the reactive function’s return value, just subscribe to it with $.
I use it a lot and it works very well for me. I’m amazed at how easily I can create such neat abstractions with so little code.
I did see it a while back, but at the time, when I tested it, I had some issues with it. I really needed to get going and had some ideas how to make it work, so I went on my own. Sorry I didn’t contribute to the package. I’ll check it out again soon.
Just one other little tid-bit to go along with @jam answer (which is correct)…in case your newer to Meteor. Be sure that if you only need 1 document, its best to try and have your publication only return’s 1 document.
@rdb I just had a look at this package and it seems very promising, especially more concise and integrated. However, this line in the README makes me unconfortable using it in production:
This package is still experimental. Use at your peril.