React meteordata mixin race conditions crashing app

I’m currently testing out React with 1.2 and enjoying it, except for 1 little bug that seems to manifest itself in so many ways.

At the moment I’m using autopub for prototyping, meaning subscriptions are not needed as of yet.

My current pattern as of now is to pass down document IDs as props where needed, and get the major components (pages) to fetch the documents in getMeteorData.

The problem arises whenever I pass down an ID as a prop (for example from a routing URL) before the collection is ready.
getMeteorData will return undefined or empty array depending on if I use findOne or fetch respectively.

This means that in all my other code, I often assume that this.data.someObject exists because I know it does in the DB. I don’t test for undefined or empty every single place I use this.data if I know it exists in the DB.

The problem is that React fatally crashes the app because it attempts to do operations on undefined objects further down, and doesn’t re-render.

It doesn’t happen when the app is fully loaded on a main screen and you click links. Only when an app is reloaded on some routing like /post/:_id where the _id is know before the collection is loaded.

Is there a good way to block this with autopub on and avoid tests on every single this.data object in render()? Will it disappear if I generate publications and wait for ready?

This solution feels a bit daft…
render(){ if(this.data.requiredObject1 === undefined || this.data.requiredObject2 === undefined) return <AppLoading />; }

If you’re passing your data values into your components as props, you can look into leveraging React’s getDefaultProps function to set defaults until your data is loaded and passed in. Another way you can handle this is by using initializer values for your data objects yourself, then making sure you don’t re-assign to those objects until the subscription is ready. So something like:

getMeteorData() {
  const car = {
    doors: 0,
    wheels: 0
  };
  const handle = Meteor.subscribe('allCars');
  if (handle.ready()) {
    car = Cars.findOne();
  }
  return {
    car
  };
}

That being said, safety checking everywhere isn’t necessarily a bad idea (within reason of course). If your code is designed to be modular your components could be re-used in more places than you originally intend. Having extra safety checks within the components themselves promotes re-usability.

The props is passed correctly since it’s being sent in from route, the problem lies with the collection not being ready.

Your code would in theory function, however it would in most cases be even more verbose, and might not always fix the issue.

For the current project i have collections such as Companies, Branches, Contracts being subscribed within the same Component.
The problem arises when I for instance look up a single contract from a URL with the route: /contracts/:_id

in my render() I can for example do a call to this.data.contract.nextEvent() which is a helperfunction in the collection. Before the collection is completed, this.data.contract is undefined and will give apparently a fatal error. In Blaze this error was never fatal since it was rerendered. But getMeteorData is never called again for a re-render.
Mocking the object is exceptionally verbose when using collection-helpers like that.

An alternative I’m seeing is doing a this.data.loading = true by default and setting it to false upon all subscribe handlers ready.

Then in render():
if(this.data.loading) return ( <AppLoading /> );

I think there should be a boolean Meteor.allSubscriptionsReady() function to ensure no subscriptions are still downloading. And adding this with a mixin perhaps?

This mixin should ensure that the component does not render, or replaces the component with loading component while subscriptions are still downloading.

Is such a thing possible?