Search code examples
javascriptreactjsbrowserifyreactjs-fluxreact-router

how to use react-router? it shows warnings


I use the following dependencies with CommonJS.
I am trying to render App and Home together.
Home component should only render when DefaultRoute's path is path="/" or path="home".
but for some reasons, I got lots of warnings.
What am I missing?
I've spent days by followings a bunch of examples and tutorials..
Any hint or solution would be very appreciated.

package.json

"dependencies": {
  "browserify": "~> 10.2.4",
  "browserify-incremental": "^3.0.1",
  "coffeeify": "~> 0.6",
  "events": "^1.0.2",
  "flux": "^2.0.3",
  "i18next-client": "^1.10.2",
  "object-assign": "^3.0.0",
  "react": "^0.13.3",
  "react-router": "^0.13.3",
  "reactify": "^1.1.1"
}

app.js

var Main = require("./main.js");
var Router = require("react-router");
var Route = Router.Route;
var DefaultRoute = Router.DefaultRoute;
var RouteHandler = Router.RouteHandler;
var Home = require("./components/home.js.jsx");

var App = React.createClass({
  getInitialState: function(){
    return {
      signedIn: null,
      currentUser: null
    };
  },
  componentWillMount: function(){
    $.ajax({
      url: "/is_signed_in",
      method: "GET",
      dataType: "json"
    }).success(function(response){
      this.setSignedIn(response);
    }.bind(this));
  },
  componentDidMount: function(){
    Main();
  },
  setSignedIn: function(response){
    this.setState({ signedIn: response.signed_in, currentUser: $.parseJSON(response.current_user) });
    console.log(Home);
  },
  render: function(){
    // <RouteHandler signedIn={this.state.signedIn} />
    return (<RouteHandler />);
  }
});

// React.render(<App />, document.body);

var routes = (
  <Route handler={App}>
    <DefaultRoute handler={Home} />
  </Route>
);

Router.run(routes, function(Handler){
  React.render(<Handler/>, document.body);
});

Logs

Warning: Failed Context Types: Required context `routeDepth` was not specified in `RouteHandler`. Check the render method of `App`.
Warning: Failed Context Types: Required context `router` was not specified in `RouteHandler`. Check the render method of `App`.
Warning: owner-based and parent-based contexts differ (values: `undefined` vs `1`) for key (routeDepth) while mounting RouteHandler (see: http://fb.me/react-context-by-parent)
Warning: owner-based and parent-based contexts differ (values: `undefined` vs `function (props, context) {
      // This constructor is overridden by mocks. The argument is used
      // by mocks to assert on what gets mounted.

      if ("production" !== "development") {
        ("production" !== "development" ? warning(
          this instanceof Constructor,
          'Something is calling a React component directly. Use a factory or ' +
          'JSX instead. See: https://fb.me/react-legacyfactory'
        ) : null);
      }

      // Wire up auto-binding
      if (this.__reactAutoBindMap) {
        bindAutoBindMethods(this);
      }

      this.props = props;
      this.context = context;
      this.state = null;

      // ReactClasses doesn't have constructors. Instead, they use the
      // getInitialState and componentWillMount methods for initialization.

      var initialState = this.getInitialState ? this.getInitialState() : null;
      if ("production" !== "development") {
        // We allow auto-mocks to proceed as if they're returning null.
        if (typeof initialState === 'undefined' &&
            this.getInitialState._isMockFunction) {
          // This is probably bad practice. Consider warning here and
          // deprecating this convenience.
          initialState = null;
        }
      }
      ("production" !== "development" ? invariant(
        typeof initialState === 'object' && !Array.isArray(initialState),
        '%s.getInitialState(): must return an object or null',
        Constructor.displayName || 'ReactCompositeComponent'
      ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));

      this.state = initialState;
    }`) for key (router) while mounting RouteHandler (see: http://fb.me/react-context-by-parent)
Uncaught TypeError: Cannot read property 'getRouteAtDepth' of undefined
Warning: Failed Context Types: Required context `routeDepth` was not specified in `RouteHandler`. Check the render method of `App`.
Warning: Failed Context Types: Required context `router` was not specified in `RouteHandler`. Check the render method of `App`.
Warning: owner-based and parent-based contexts differ (values: `undefined` vs `1`) for key (routeDepth) while mounting RouteHandler (see: http://fb.me/react-context-by-parent)
Warning: owner-based and parent-based contexts differ (values: `undefined` vs `function (props, context) {
      // This constructor is overridden by mocks. The argument is used
      // by mocks to assert on what gets mounted.

      if ("production" !== "development") {
        ("production" !== "development" ? warning(
          this instanceof Constructor,
          'Something is calling a React component directly. Use a factory or ' +
          'JSX instead. See: https://fb.me/react-legacyfactory'
        ) : null);
      }

      // Wire up auto-binding
      if (this.__reactAutoBindMap) {
        bindAutoBindMethods(this);
      }

      this.props = props;
      this.context = context;
      this.state = null;

      // ReactClasses doesn't have constructors. Instead, they use the
      // getInitialState and componentWillMount methods for initialization.

      var initialState = this.getInitialState ? this.getInitialState() : null;
      if ("production" !== "development") {
        // We allow auto-mocks to proceed as if they're returning null.
        if (typeof initialState === 'undefined' &&
            this.getInitialState._isMockFunction) {
          // This is probably bad practice. Consider warning here and
          // deprecating this convenience.
          initialState = null;
        }
      }
      ("production" !== "development" ? invariant(
        typeof initialState === 'object' && !Array.isArray(initialState),
        '%s.getInitialState(): must return an object or null',
        Constructor.displayName || 'ReactCompositeComponent'
      ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));

      this.state = initialState;
    }`) for key (router) while mounting RouteHandler (see: http://fb.me/react-context-by-parent)
Uncaught TypeError: Cannot read property '_currentElement' of null

home.js.jsx

var home = function(){

  var HomeHero = React.createClass({
    componentWillMount: function() {
      document.getElementsByClassName("homeHero")[0].className = "homeHero container header pure-u-1 u-size1040";
    },
    render: function() {
      return(
        <div className="hero textAlignCenter">
          <h1 className="hero-logo"><a href="/">LOGO</a></h1>
          <h2 className="hero-description">DESCRIPTION.</h2>
        </div>
      );
    }
  });

  var Home = React.createClass({
    render: function() {
      return (
        <div>
        Home
       </div>
      );
    }
  });

  React.render(<HomeHero />, document.getElementsByClassName("homeHero")[0]);
  React.render(<Home />, document.getElementsByClassName("home")[0]);

};

module.exports = home;

Finally Fixed The Problems! I actually use Ruby on Rails framework and react-rails gem. I suppose the react files from the gem is different with original react. As soon as I replace react gem files with react installed from npm, everything worked.

damn...it took me several days to figure out. thank you for all of the answers guys.


Solution

  • The following example works error free:

    (I also have a gulpfile doing a babelify transform with browserify - putting react and react-router into a separate file named vendors.js - ommitted here)

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Testing</title>
      </head>
      <body>
    
      </body>
      <script type="text/javascript" src="dist/vendors.js"></script>
      <script type="text/javascript" src="dist/app.js"></script>
    </html>
    

    app.jsx

    var React = require('react');
    var Router = require('react-router');
    var Route = Router.Route;
    var DefaultRoute = Router.DefaultRoute;
    var RouteHandler = Router.RouteHandler;
    
    var Home = React.createClass({
      render: function(){
        return (
            <h1>Home</h1>
          )
      }
    });
    
    var App = React.createClass({
      render: function(){
        return (
          <div>
            <RouteHandler />
          </div>
          )
      }
    });
    
    var routes = (
      <Route path='/' handler={App}>
        <DefaultRoute handler={Home} />
      </Route>
    );
    
    Router.run(routes, function(Handler){
      React.render(<Handler/>, document.body);
    });
    

    react-router handles much of the heavy lifting for you. If you want to render to a different location, you change that in the render.

    Router.run(routes, function(Handler){
      React.render(<Handler/>, document.getElementById('someId'));
    });
    

    With your added home code, if you want to have a router there, you can also do that as well following a similar pattern as above, and add a <RouteHandler /> to the home module.

    The docs are really helpful - but it's easy to get out of their scope with your complexity. I've done a few complex route schemes - it can all be done.

    EDIT Added a repo to this here - https://github.com/kellyjandrews/react-touter-testing

    I went ahead and include all of the node modules - mostly because I was lazy and didn't validate my package.json. Should be able to run gulp from the folder, and you will see "Home" in the browser. If you are getting warnings from this - you have something going on that I can't fix from here.