React + Komposer, signing out triggers lots of errors

I’m using React and React Komposer for my app, with subscriptions based on the user.

On logout, I defined a small function at the top of my routes.js file that looks like this:

// Automatically route someone who logs out to the homepage
if (Meteor.isClient) {
  Accounts.onLogout(function () {
    FlowRouter.go('/');
  });
}

Logging out removes the subscriptions based on the user, and therefore the main document I refer to everywhere in my app becomes undefined (correct behaviour).

However, this triggers several warnings and errors in my console:
All components which were on screen and rely on this document as a prop (which I made required in the proptypes), tell me that it is undefined:

myDocument is marked as required in `myComponent`, but its value is `undefined`.

Also, the components who access a deeper element in the prop give me this error:

Cannot read property 'mySubProperty' of undefined

Both make sense, since the myDocument prop is undefined for a short amount of time, but I’d like to know how to properly log out and prevent these errors from showing up?

The components that rely on the user beeing logged in or that rely on myDocument which is only available when logged in should not be rendered when the user has logged out.

// somewhere in a container:

const composer = ({context}, onData) => {
  const { Meteor } = context();
  const user = Meteor.user();
  onData(null, {user});
}


// somewhere in a ui-component

const MainLayout = ({user}) => (
   <div>
  { user ? 
      <UserLoggedInLayout /> :
      <UserNotLoggedInLayout />
  } 
  </div>
)

UserNotLoggedInLayout then should not contain any component that rely on the user.

Also, consider that the user can be logged in, but this document is not there, so you should always check these things:


const composer = ({context}, onData) => {
   const { Meteor, Collections } = context();
  if(Meteor.subscribe("myuserdata").ready() {
      const myDocument = Collections.SomeCollection.findOne( {userId} );
      if( myDocument )  {
        onData(null, {myDocument});
     } else {
        onData(new Error("document not found"))
     }
  }

}

```

Indeed that solved it for me, I was doing the same check in my layout but with Meteor.user() (which isn’t reactive) instead of a composer function to fetch the current user.

I’m curious about the way you use the context variable, all of my composer functions start like this:

const composer = (props, onData) =>

I import Meteor on the top of the file from 'meteor/meteor', I have to say I’ve never used the props variable in a composer function anyways. So what does context() represent?

Last question, I saw a lot of people using:

else {
        onData(null, null)
     }

instead of what you suggest with a new Error(), what are your thoughts on that?

Thanks a lot!

the context is from the mantra-spec https://kadirahq.github.io/mantra/

it is basically an object with injected properties. This way, you can test it more easily (e.g. you can mock Meteor).
It uses https://github.com/kadirahq/react-simple-di

you can ignore that in the example above, it was just a habit :wink:

the props however, are the props that are passed to the container:


<MyContainer showNavigation limit={5} />

// container:

const composer = ({showNavigation, limit}, onData) => //...

Edit: second question,

if you pass an error as first param, it will render a predefined error-component, not the composed component.