14

I've been following along Tyler Mcginnis' tutorial and hit a snag with the react router, specifically with history. I ended up copying his code verbatim just to see if it was only me, but I'm still getting

Warning: React.createElement: type is invalid -- expected a string (for built-
in components) or a class/function (for composite components) but got:
undefined. You likely forgot to export your component from the file it's 
defined in.

Warning: Failed prop type: The prop `history` is marked as required in 
`Router`, but its value is `undefined`. in Router

Uncaught TypeError: Cannot read property 'location' of undefined
at new Router (index_bundle.js:8347)
at index_bundle.js:19079
at measureLifeCyclePerf (index_bundle.js:18859)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (index_bundle.js:19078)
at ReactCompositeComponentWrapper._constructComponent (index_bundle.js:19064)
at ReactCompositeComponentWrapper.mountComponent (index_bundle.js:18972)
at Object.mountComponent (index_bundle.js:4070)
at ReactCompositeComponentWrapper.performInitialMount (index_bundle.js:19155)
at ReactCompositeComponentWrapper.mountComponent (index_bundle.js:19042)
at Object.mountComponent (index_bundle.js:4070)

The implementation is:

var React = require('react');
var ReactRouter = require('react-router');
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var hashHistory = ReactRouter.hashHistory;
var IndexRoute = ReactRouter.IndexRoute;
var Main = require('../components/Main');
var Home = require("../components/Home");
var PromptContainer = require('../containers/PromptContainer');

var routes = (
  <Router history={hashHistory}>
    <Route path='/' component={Main}>
      <IndexRoute component={Home} />
      <Route path='playerOne' header='Player One' component={PromptContainer} />
      <Route path='playerTwo/:playerOne' header='Player Two' component={PromptContainer} />
    </Route>
  </Router>
);

module.exports = routes;

What I noticed was that hashHistory doesn't exist in the react-router module, but rather there is a createBrowserHistory inside the history module. Following the API doc I found, I figured I must call it through there as:

var BrowserHistory = require('history/createBrowserHistory);
const history = createBrowserHistory();

Doing that produces an createBrowserHistory is not a function error. Removing paranthesis, results in the same errors above stating history is undefined.

When I log history, it's definitely undefined, which makes me believe the issue has to do with the import statement, but wouldn't the console tell me ReactRouter.hashHistory could not be found?

I understand this tutorial is a year old and there have probably been changes to the API I just not aware of, and that's where my issue lies. Any help is appreciated!

JoeDahle
  • 163
  • 1
  • 1
  • 6

2 Answers2

33

Router v4 is a little bit different

HashHistory

import { HashRouter as Router, Route } from 'react-router-dom'; 
import App from './components/App'; 

render(( 
  <Router> 
    <Route exact path="/" component={App} /> 
  </Router> ), 
document.getElementById('root'));

or BrowserHistory

import { BrowserRouter as Router, Route } from 'react-router-dom'; 
import App from './components/App'; 

render(( 
  <Router> 
    <Route exact path="/" component={App} /> 
  </Router> ), 
document.getElementById('root'));
Nicholas
  • 3,529
  • 2
  • 23
  • 31
  • 1
    I'm reverting to v3 to complete this tutorial, then I'll move onto v4 api, but it's good to know that those changes were made. I'll mark this as the answer, for others to see, thanks! – JoeDahle Mar 16 '17 at 23:06
  • Multiple routes give error: "Uncaught Error: A may have only one child element". How to fix that? – olefrank Apr 05 '17 at 20:58
  • @olefrank, what version of router? [This might help you](https://github.com/ReactTraining/react-router/issues/4131), search where there is an answer with `Switch` tag in router. – Nicholas Apr 07 '17 at 17:51
0
var BrowserHistory = require('history/createBrowserHistory');
const history = createBrowserHistory();

do you mean var createBrowserHistory = require...?

also, it looks like createBrowserHistory is now (in v3) located at history/lib/createBrowserHistory

If that doesn't work - what version of react-router are you using?

Tyler Sebastian
  • 9,067
  • 6
  • 39
  • 62
  • 1
    Right, createbrowserhistory.... I didn't copy paste that part. I'm using history version 4.6.1, and it's not in /lib either. Reactrouter is v 4.0.0 – JoeDahle Mar 16 '17 at 22:18
  • @JoeDahle yeah ok v4 broke a *lot* of things. If you're following a guide from a year ago, I'd use v3. – Tyler Sebastian Mar 16 '17 at 22:22
  • It is v4 that breaks everything, I reverted to v3.0.2, and everything works as hoped for, thanks! – JoeDahle Mar 16 '17 at 23:04