I have a Tracker.autorun() in my client code that automatically subscribes to my user’s notifications, like this:
Tracker.autorun(async function() {
const subscription = Meteor.subscribe('notifications:notifications');
if (!subscription.ready()) return;
... fetch the notifications ...
});
This worked in Meteor 2. But in Meteor 3, the autorun() won’t be triggered if the ready() state changes. I assume that ready() is not reactive anymore? Is there some documentation about this change, and how can such a reactive listener be achieved in Meteor 3 now?
I moved away from reactive subs within Tracker computations because they interfered too much and I used the callbacks instead (onReady and onError) which are pretty stable. Using them in combination with reactive-var/-dict works very well in Blaze.
Thanks for the fast response. I am on Meteor 3.0.4. The sub actually becomes ready, as I can check with @jkuester’s approach. I found the code for ready() in the meantime and saw it stil had a depend call, but still my autorun() won’t re-run if the sub gets ready.
Nope, I do not wrap then. I wasn’t aware this is neccessary and did not see it in the Meteor 3 upgrade docs. This could explain why the ready() call never triggers, because I have an await Meteor.userAsync() before that call.
I’m a bit confused with the docs. Is this pseudo-code (i.e. Computation is a type)?
It is a function from "meteor/tracker" that requires a Computation type object as first param and has a function as it second param.
Yes lol! I just checked, and I have mistakenly transcribed this part in the past
This was one of the sources:
// needs Tracker.withComputation because otherwise it would be only called once, and the computation would never run again
Tracker.autorun(async (c) => {
const placeholders = await fetch('https://jsonplaceholder.typicode.com/todos').then(x => x.json());
console.log(placeholders);
const data = await Tracker.withComputation(c, () => LinksCollection.find().fetchAsync());
console.log(data);
});
I’ll write a PR updating those mistakes!
but basically, a rule of thumb is that if you are using a reactive function for example find + fetchAsync (Meteor.userAsync() uses it under the hood), it is nice to wrap it inside Tracker.withComputation
Thanks. This seems to work, without the endless loop.
I am wondering: I always thought that the first run of a reactive function would determine which code be used to trigger re-runs. That was the main reason why I had placed the userAsync() call before the ready() call. But I still get re-runs now when the user object changes (what I want), although the ready() would return on the first call. So I guess that every run will actually add reactive triggers if the code is at least touched once?
which also confuses me a bit. I wasn’t aware that useTracker() also needs Tracker.withComputation. And the sample does not really explain why exactly the first version needs withComputation, but the second won’t. Is it becaue it is the only async call and thus the first one?