TrackerReact: No-Config reactive React Components - Now ready for Meteor 1.3

TrackerReact has been around for some time as an alternative to the getMeteorData() mixin and is the brainchild of @faceyspacey.

meteor add ultimatejs:tracker-react

Due to personal frustration with the ongoing configuration creep - from the build tools now into the view layer - I gave TrackerReact an overhaul to provide an easy way to get going with Meteor & React. A way that doesn’t feel clunky and doesn’t require upfront investments into event sourcing systems or containerisation.

So it is well suited for small to mid-sized applications which tend to be wide (many simple features) instead of tall (a few, very complicated features; like a web IDE for example).

// Simply compose a reactive React.Component with TrackerReact by wrapping it.
class App extends TrackerReact(React.Component) {

  tasks() {
    return Tasks.find({}).fetch();
  }

  render() {
    return (
      <ul>
        {this.tasks().map((task) => {
          return <Task key={task._id} task={task} />;
        })}
      </ul>
    );
  }
}

With TrackerReact, a React Component becomes reactive for any of Meteors Reactive Data Sources (Collections, Methods, Sessions etc.). Components can be suggered as composition (seen above), as a mixin or as a decorator.

For package details please check our GitHub Repo:

For some guidance on code implementation with - for some of us still alien - ES6 syntax, please take a look at the following example app. Particularly its source code.

class App extends TrackerReact(React.Component, {profiling: true})

PS: Of course Meteor 1.3 is still in beta. So beware.

20 Likes

Which profits it gives from getMeteorData?

The ability to access a reactive data source from anywhere in your component code is really cool (although I would probably still maintain the container/component separation), but are there any downsides to using this package? Would it trigger more re-renders than the mixin?

It “unfreezes” reactive computations from one big method getMeteorData, allowing you to use reactive data sources more natural with several “compact methods”. I.e. no need for abstractions like this.data.foo.

So beside being more declarative, everything is the same. By having you subscribe & unsubscribe to data, it also appears less magic which seems to sound better with react devs, that had no prior experience with Meteor. Subscriptions awareness is also essential for mixed blaze <-> react apps. But in the end, just a matter of taste.

Containers (“wrapper components with no special render task”) are good practice to centralize data flow - just suger an empty TrackerReact container - but feels often overhead when prototyping or testing new, isolated features.

I see minimongo similar purposed to redux (state management library), just without immutability… and no testing story. So for clarity, rendering in the same component can than be okay as well.

There should be no performance difference. getMetoerData() also triggers a re-render of the whole component. But keep in mind, that thanks to the virtual dom, rendering has nothing to do with DOM rendering. It is in fact so efficient, that you can assume it is free. I…e. I power with TrackerReact a BI dashboard with over 6000 documents and no problems.

So rendering is a complete different story compared to blaze - how the great @arunoda put it:

3 Likes

I am still using this for container/component separation, but it is much nicer to see the code in a much cleaner way imo. I tried to teach people react-komposer and it is very confusing that it generates containers behind the scenes. Just create a React class jsx file that brings in some data and then render out the dumb components you need by passing them props.

2 Likes

Sorry for interrupt you guys with some offtopic, but if you are talking about containers and “dumb” components… What is a meteor way to get input data from a “dumb” component and pass it to a container to handle it? How I understand, react way is to use redux. What about meteor?

That is a basic react thing, just pass your ‘action’ methods down to the dumb component and it can call it, then you can use this.refs, etc.

Ooops,I tried to reproduce the bug and as results it just works fine! I’ve spent whole evening trying to handle it, started to learn about Redux, and it was just a typo somewhere. Thanks ><

@dinos Thanks a million for this!
It actually ‘feels’ like React. GetMeteorData ‘feels’ like a hack.
I hope MDG mentions this in the new 1.3 guide.

3 Likes

TrackerReact has been updated to fix an issue with a “bug” in react of missing inheritance of componentWillUnmount() that triggered a warning on unmounting a reactive component. Also the TrackerReact-Example was updated.

Additionally, a profiler has been added to have a better view on performance. Easily activated by composing a TrackerReact component with a second argument:

class App extends TrackerReact(React.Component, {profiling: true})
3 Likes

This one is quite interesting. Actually i have been using mantra as our application architecture but the container approach for something simple like autocomplete component feels a little too overbearing. I still think that container approach is better in the long run and large applications as it makes it easier to debug and we know where things are present.

Such a coincident, we just released another really easy method to get React and Tracker integration, one cannot make it easier, and the implementation can’t be lighter, it’s ridiculous how easy we’ve made it.

We’ve reimplemented the Blaze templates methods autorun and subscribe for React, and guess what it makes perfect sense doing that, using 50 lines of code for the integration, one can’t argue against that right?

And as a bonus feature: it’s also easy to use this method for Server Side Rendering (see the clip to learn how)

The clip includes a short demo of how we build easy React Components with Meteor 1.2 and Tracker using Tracker.Component, and how it all works.

Demo and instructions for 1.3 is on the way, just not tonight :smile:

Cheers from the folks at Studio Interact

3 Likes

Thank you so much for doing this.

Is there a reason why you’re calling forceUpdate instead setState with an empty object? That way you would trigger the re-render but still respect shouldComponentUpdate.

Mh, to be honest, I can’t remember. But if the behavior is 1:1, this is certainly a great suggestion. Have you tried it?

Yeah and as far as I can tell it’s 1:1 so I asked =)

Well, awesome, than I’ll change it on the next push. :muscle: