React Router not rendering React Component


#1

I am trying to get up to speed with React and the react Router, but I am having problems in figuring it out. I started with the meteorChef’s base meteor install (https://themeteorchef.com/base/). From that i was able to get his routing working to /login. But when I try to go to my own page (routed at /) that should show some tiled pictures, I am not seeing anything getting rendered.

Here is my router (main.js):

import React from 'react';
import { render } from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import { Meteor } from 'meteor/meteor';
import { App } from './app.js';
import { Index } from './index.js';
import { Login } from './login';

Meteor.startup(() => {
  render(
    <Router history={ browserHistory }>
      <Route path="/" component={ App }>
        <IndexRoute name="index" component={ Index } />
        <Route name="index" path="/index" component={ Index } />
        <Route name="login" path="/login" component={ Login } />
      </Route>
    </Router>,
    document.getElementById('react-root')
  );
});

Here is what I am trying to render index.js

import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { createContainer } from 'meteor/react-meteor-data';
import { Portfolios } from '../imports/getPortfolio.js';

import Portfolio from './portfolio.jsx';

// App component - represents the whole app
class Index extends Component {
  constructor(props) {
    super(props);
  }
  handleSubmit(event) {
    event.preventDefault();

    // Find the text field via the React ref
    const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
    const image = ReactDOM.findDOMNode(this.refs.imageInput).value.trim();

    Meteor.call('portfolios.insert', text,image);

    // Clear form
    ReactDOM.findDOMNode(this.refs.textInput).value = '';
    ReactDOM.findDOMNode(this.refs.imageInput).value = '';
  }

  renderPortfolios() {
    let displayPortfolios = this.props.portfolios;
    return displayPortfolios.map((portfolio) => (
      <Portfolio key={portfolio._id} portfolio={portfolio} />
    ));
  }

  render() {
    return (
      <div className="my-portfolio">
        <header>
          <h1>Portfolio List ({this.props.count})</h1>

          <form className="new-portfolio" onSubmit={this.handleSubmit.bind(this)} >
            <input
              type="text"
              ref="textInput"
              placeholder="Type to add new portfolios"
            />
            <input 
              type="text"
              ref="imageInput"
              placeholder="Image location"
            />
            <button type="submit">Submit</button>

          </form>
        </header>

        <ul className="ul-portfolios">
          {this.renderPortfolios()}
        </ul>
      </div>
    );
  }
}

Index.propTypes = {
  portfolios: PropTypes.array.isRequired,
  count: PropTypes.number.isRequired,
};

export default createContainer(() => {
  Meteor.subscribe('portfolios');
  return {
    portfolios: Portfolios.find({}, { sort: { createdAt: -1 } }).fetch(),
    count: Portfolios.find({ checked: { $ne: true } }).count(),
  };
}, Index  );

And here is app.js

import React from 'react';
import { Grid } from 'react-bootstrap';

export const App = React.createClass({
  propTypes: {
    children: React.PropTypes.element.isRequired,
  },
  render() {
    return <div>
      <Grid>
        { this.props.children }
      </Grid>
    </div>;
  },
});

You can see the code on github here: https://github.com/Kenny4444/reactRouterTest

The router is client/main.js and its client/portfolio.jsx that I am trying to render (called index in main.js)

Can someone take a look and help a react beginner out? Thanks!


#2

Also if I change the main.js to be the following:

import React from 'react';
import { Meteor } from 'meteor/meteor'; 
import { render } from 'react-dom'; 
 
import App from './index.js';
 
Meteor.startup(() => {
  render(<App />, document.getElementById('react-root'));
});

It works just fine. I must be doing something that is incompatible with the router. But can’t seem to figure out what that would be.


#3

Figured out my first error. I needed to add an export onto the Index class …whoops :blush:.

Now I have the following problems:

warning.js:44Warning: Failed propType: Required prop `portfolios` was not specified in `Index`. Check the render method of `RouterContext`.warning 
warning.js:44Warning: Failed propType: Required prop `count` was not specified in `Index`. Check the render method of `RouterContext`.

#4

I changed to use the Flow router you can find that here https://github.com/Kenny4444/flowRouterTest: and I am getting these error.

warning.js:44Warning: Failed propType: Required prop `portfolios` was not specified in `Index`.
warning.js:44Warning: Failed propType: Required prop `count` was not specified in `Index
warning.js:44 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).

@arunoda can you possibly help me figure out whats going on here. I am struggling to find any information on using the react-meteor-data/createContainer pattern with a router and any guidance would be greatly appreciated.