We have several fairly large Meteor apps running on 2.13 and are in the process of migrating to Meteor 3.
All of our apps have a shared core with a lot of isomorphic code, which we need to make async for Meteor 3. A lot of this isomorphic code is used in useTracker
on the client-side.
The official V3 migration guide for React instructs to use the suspense version of useTracker
, which can handle async functions, but we found several issues blocking us and we are not sure how to proceed:
- If we put a Suspense high in the component tree it results in a buggy mess, sometimes react errors about bad setStates are thrown and the app never loads
- Putting the Suspense just above the trackers makes things better at first glance, but we start running into the issues below
- Using between 1 and 4 suspense trackers in one component results in flaky UI flashes (sometimes no flashes, sometimes several)
- Using more than 5 suspense trackers in one component starts making things unusable, where each one makes it exponentially worse. UI flashes several times and each flash takes several seconds, resulting in atrocious loading times. Using Tracker.withComputation inside the suspense tracker seems to only make things worse.
- FindOneAsync does not seem to keep its reactivity, even with Tracker.withComputation. Changing to FindOne instantly brings the reactivity back. We found that using a workaround of
.find.fetchAsync()[0]
still keeps things reactive.
Keep in mind all we are doing is replacing the normal trackers with the suspense ones (collection data is received from global subscriptions). It doesn’t matter if the tracker returns a promise or not. The problem can easily be reproduced like this:
const a = useTracker('a', () => Collection1.find().fetchAsync());
const b = useTracker('b', () => Collection2.find().fetchAsync());
const c = useTracker('c', () => Collection3.find().fetchAsync());
const d = useTracker('d', () => Collection4.find().fetchAsync());
const f = useTracker('e', () => Collection5.find().fetchAsync());
const e = useTracker('f', () => Collection6.find().fetchAsync());
This is the most basic of examples, with which we are running into problems. Ideally we would use our shared isomorphic code in the trackers, which can call several async methods, have additional logic, etc.
We are running into this problem on both Meteor 2.13 and 3.3.1. Versions of related packages:
react-meteor-data@4.0.0
react: 18.2.0
Are we missing/misunderstanding/misusing something? To us it looks like the suspense trackers are an experimental feature, yet they are a part of the official migration guide.