[Help!] React and Flow Router - Open in new tab


#1

Hi all,

I have a fairly basic and rudimentary forum that I’ve made only accessible to logged in and verified users. However, when someone wants to open a post in a new tab, it kicks them off saying they’re either not logged in or unverified. Here’s some code:

FlowRouter.route('/forums/:_id', {
  triggersEnter: [function(context, redirect) {
    if (!Meteor.user() || Meteor.user().emails[0].verified == false) {
      FlowRouter.go('/');
      Bert.alert({title: "Not logged in or not verified", type: 'danger', icon: 'fa-times', style: 'growl-top-right'});
    }
  }],
  name: "PostPage",
  action: function(params) {
    mount(MainLayout, {
      content: (<PostPage _id={params._id} />)
    });
  }
});

I think it’s more a flow-router issue than a React issue, but would be good to know what I’m doing wrong here.

Thanks,

Tom.


#2

Meteor.user() is reactive so the user might not have loaded yet when you do the user check. If you want your router to handle auth logic then you’ll likely want to wrap your Meteor.user() check in a Tracker.autorun (you might also want to add in a Meteor.loggingIn() check).

Just as an aside - FlowRouter recommends using template level auth handling for a few reasons, one of which is this exact issue (having to wait for data to be ready in the router doesn’t necessarily provide the best user experience). See the Implementing Auth Logic and Permissions section of Kadira’s Routing Guide for more info.


#3

That definitely sounds like the best option. It looks like that post also has React examples.

Thanks a lot!


#4

Hmmm. The suggested method above doesn’t seem to work for me.

I’m getting the following errors (as an example):

Uncaught TypeError: Cannot read property '__reactInternalInstance$tj2hftd5sqxfcmdpxjldz33di' of null

Any idea what this means? Also getting this just above:

TypeError: Cannot read property '_currentElement' of null

I’m assuming it’s trying to load the page before it’s got all the necessary information through props (it only does it on pages like a forum post or whatever). I’m not savvy enough to figure out a solution myself though. So further help will be excellent.

Thanks,

Tom.


#5

Do you have any code examples of where these Errors are coming from? Are they coming from js in your react component?


#6

Hi @foxder,

Good idea! I’ll share one of my components and the route to it:

Component:

import React from 'react';

GamesPage = React.createClass({
  mixins: [ReactMeteorData],

  // Load items
  getMeteorData () {
    Meteor.subscribe("servers");
    return {
      server: Servers.findOne({ slug: this.props.slug })
    }
  },

  componentDidMount() {
    var title = this.data.server.title + " | The Realm Gaming";
    DocHead.setTitle(title);

    var metaInfo = {name: "description", content: this.data.server.title + " at The Realm Gaming"};
    DocHead.addMeta(metaInfo);

    var fragment = {name: "fragment", content: "!"};
    DocHead.addMeta(fragment);
  },

  renderAddress() {
    if( this.data.server.address ) {
      return <p><b>Server Address:</b> { this.data.server.address }</p>;
    } else {
      return;
    }
  },

  renderManagers() {
    if( this.data.server.managers ) {
      return <p><b>Managers:</b> { this.data.server.managers }</p>;
    } else {
      return;
    }
  },

  renderWebsite() {
    var smallMargin = { marginTop: '10px' };
    if( this.data.server.website ) {
      return <a className="btn btn-success sharp" style={ smallMargin } href={ this.data.server.website }>Server Website</a>;
    } else {
      return;
    }
  },

  renderDesc() {
    desc = parseMarkdown( this.data.server.rules );
    return <div dangerouslySetInnerHTML={{__html: desc}}></div>;
  },

  render() {
    var divStyle = {
      backgroundImage: 'url(' + this.data.server.cover + ')'
    }
    return (
      <div className="wrapper">
        <div className="cover-photo" style={ divStyle }>
        </div>
        <div className="profile-top container">
          <h1 className="text-center white shadowed">{ this.data.server.title }</h1>
        </div>
        <div className="container game-container">
          <div className="row">
            <div className="col-md-3">
              <div className="panel panel-default sharp bio">
                <div className="panel-body">
                  <h3 className="text-center">Info</h3>
                  <hr></hr>
                  { this.renderAddress() }
                  { this.renderManagers() }
                  { this.renderWebsite() }
                </div>
              </div>
            </div>
            <div className="col-md-9">
              { this.renderDesc() }
            </div>
          </div>
        </div>
      </div>
    )
  }
});

Note that this doesn’t have the method mentioned in the Kadira post above because it makes no difference. If I do it the same way @arunoda suggests it reacts in the same way. Maybe it’s react-mounter?

Here’s the route anyway:

FlowRouter.route('/games/:slug', {
  name: "GamesPage",
  action: function( params ) {
    mount(MainLayout, {
      content: (<GamesPage slug={ params.slug } />)
    });
  }
});

Cheers,

Tom.


#7

Just from googling around for the error I came across these two resources for you:



#8

Thanks for those links. The first one (regarding setState) doesn’t seem to apply in my case. I’m not passing any state with the code I showed above as it’s a ‘static’ page with content coming from mongo.

The second one has a few issues in there, but again can’t pinpoint the error I’m getting. If I have a properly defined route, such as /forums or /games with no props to pass down, the url works fine and I can open in new tab without issues.

It’s only when I want something like /forums/:_id or /games/:slug that I have a problem. Unfortunately, as we know this is a key part of the app… It’s really frustrating. It also means prerender isn’t caching my pages. Sad times :disappointed_relieved:

It’s worth mentioning if you go to the pages while using the app itself, it works no problem. So if I’m sat on the homepage and click the link to a forum post or game page (in the case of this app) then it works without issue. It’s like it can’t get what it needs when re-opening the connection or something. Definitely related to Tracker in someway as well though:

The full error I get when accessing a ‘Games’ page with open in new tab is:

Uncaught TypeError: Cannot read property 'cover' of undefined
Uncaught TypeError: Cannot read property '__reactInternalInstance$3uv0xozwusgcsl0ag5z1vy4x6r' of null
Exception from Tracker recompute function:
TypeError: Cannot read property '_currentElement' of null
    at R._updateRenderedComponent (28d96c6….js?meteor_js_resource=true:32)
    at R._performComponentUpdate (28d96c6….js?meteor_js_resource=true:32)
    at R.updateComponent (28d96c6….js?meteor_js_resource=true:32)
    at R.performUpdateIfNecessary (28d96c6….js?meteor_js_resource=true:32)
    at Object.s.performUpdateIfNecessary (28d96c6….js?meteor_js_resource=true:28)
    at u (28d96c6….js?meteor_js_resource=true:28)
    at o.r.perform (28d96c6….js?meteor_js_resource=true:28)
    at r.perform (28d96c6….js?meteor_js_resource=true:28)
    at r.p.perform (28d96c6….js?meteor_js_resource=true:28)
    at Object.D [as flushBatchedUpdates] (28d96c6….js?meteor_js_resource=true:28)

Any more ideas? Anyone had a similar issue?


#9

Small edit to reply above.


#10

Uncaught TypeError: Cannot read property ‘cover’ of undefined

@korus90 What is calling .cover ? Do you mind sharing that code?


#11

Hi Foxder, thanks again for your reply.

I just had a fiddle around with it again this morning. Then I realised the router wasn’t in the lib directory (for some reason) and was instead in the client directory. Moving it into lib has fixed the open in new tab issues!

So in the end, completely my own fault. However, probably worth remembering and keeping this thread alive in case anyone else comes across this problem themselves.

Derp! Feel like an idiot. Oh well :frowning: