Two trackers better than one?

Hi,

I have a question about useTracker, guess this is a basic question but I really don’t know the answer. Which option is better performing? (Assuming that there’s already a top level sub ready publishing data from Coll1 and Coll2)

const MyComponent = () => {
   const { data1, data2 } = useTracker(() => {
      const data1 = Coll1.find().fetch();
      const data2 = Coll2.find().fetch();
      return { data1, data2 };
   });
}

or

const MyComponent = () => {
   const { data1 } = useTracker(() => {
      const data1 = Coll1.find().fetch();
      return { data1 };
   });
  const { data2 } = useTracker(() => {
      const data2 = Coll2.find().fetch();
      return { data2 };
   });
}

If any react pro could help out, that would be really great!

1 Like

For this kind of find I would use useFind instead of Tracker.

Sorry forgot to mention that I‘m on react native, an meteorrn doesn’t have this hook (yet).

Anyway, for my understanding of react, I would really like to know which design causes more rerenders, given the data doesn’t change

1 Like

For total re-renders the first one will be better, since if they both get updated at the same time it will only do one re-render.

The first one may do more computation overall if the tracker becomes more complicated, but that is very unlikely to become the bottleneck.

1 Like

If in variant 2 the cursor result of the first tracker changes, will this rerender the second?

It won’t re-run the second one, but it would rerender the component they are both in anyways

It would be more of a difference if you would be able to have both find’s in separate components. That would make a difference but whether possible depends on the data / component of course.

1 Like

That sounds reasonable; however, in my use case, data from both collections is displayed in one component.

Then there won’t be much of a difference. If there is any relevant performance issues you could look at using multiple components in some way.

<div>{data1.name} - {data2.name}</div>

Could also be rendered as for example:

<div><Data1NameComponent/> - <Data2NameComponent/></div>

But all in all it seems premature optimization based on your examples so if it works don’t make it more complicated.

If the data from Coll1 and Coll2 is relatively small and doesn't change frequently, using useTracker directly in the component might be a simple and efficient approach. On the other hand, if the data in Coll1 and Coll2 is extensive or frequently updated, it might be better to use a top-level subscription.

Direct answer: When you have a useTracker, you’ll always want to add a deps array. Otherwise the Tracker will be destroyed and a new one will be created for each rerender, which is bad! For example, if you have no deps, pass an empty array:

const data1 = useTracker(() => {
    return Coll1.find().fetch();
}, []);

Next, it’s true that using separate trackers can use less cpu cycles, but in the land of react rerenders are your enemy, not local data fetching-- I’ve never once seen anyone bother with it. Producing nice and readable code is generally preferred as the differences, especially in example code like yours is negligible.

Lastly, I should point out that the DDP implementation on the meteorrn package differs from the official implementation. I wound up copying the official meteor client into my react native project, which wound up being a great investment. It’s a difficult process, but I have posted my learnings here: Official meteor client in react native