108

I am new to ReactJs. This is my code:

var React = require('react');
var ReactDOM = require('react-dom');
var {Route, Router, IndexRoute, hashHistory} = require('react-router');
var Main = require('Main');
ReactDOM.render(
  <Router history={hashHistory}>
  <Route path="/" component={Main}></Route>
</Router>, document.getElementById('app'));

and compiling it with webpack. Also I added Main component to my aliases. The console throws these errors: I also read these links :

React Router failed prop 'history', is undefined

How do I resolve history is marked required, when value is undefined?

Upgrading React-Router and replacing hashHistory with browserHistory

and many searches around the web, but I couldn't fix this issue. React Router is version 4

Community
  • 1
  • 1
Mammad2c
  • 1,255
  • 2
  • 10
  • 13

8 Answers8

188

If you are using react-router v4 you need to install react-router-dom as well. After that, import BrowserRouter from react-router-dom and switch Router for BrowserRouter. It seems that v4 change several things. Also, the react-router documentation is outdated. This is my working code:

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

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

Source

Leon Gaban
  • 36,509
  • 115
  • 332
  • 529
betomoretti
  • 2,186
  • 1
  • 14
  • 15
  • 11
    In version 4,when you are using 'react-router-dom', there is no need to import 'react-router'. 'react-router-dom' is complete. – Mammad2c Apr 03 '17 at 11:09
  • 4
    If I have multiple tags inside BrowserRouter I get this error: "Uncaught Error: A may have only one child element". How to fix? – olefrank Apr 05 '17 at 20:56
  • @olefrank Yeah I had the same problem.. I fixed adding a
    that wrappes all components.. I'm learning as well and maybe isn't the best solution..
    – betomoretti Apr 06 '17 at 14:44
  • Question @Mammad2c . Do you need both `react-router` and `react-router-dom` in your node modules if you are saying to only import `react-router-dom`? If I am trying to use `react-router` v4 then why use `react-router-dom`? thx. – erp May 15 '17 at 17:24
  • 1
    @erp react-router-dom has more options than react-router. you could visit the document. But you have only use one of them. – Mammad2c May 18 '17 at 10:32
  • @erp Yes you will need both, as you'll need `route` from `react-router` and `HashRouter as Router` from `react-router-dom`. You want to use the HashRouter, for some reason `Router` from `react-router` doesn't work. – NSCoder May 26 '17 at 13:34
  • 2
    @NSCoder no, router also is in the 'react-router-dom' so there is no need to include both 'react-router-dom' and 'react-router'. If you need 'HashRouter' and 'router' together, you have to include 'react-router-dom'. – Mammad2c May 28 '17 at 23:41
  • 2
    @olefrank you need to wrap your multiple `` statements in `` wrapper instead of wrapping them in `
    `. If you use `
    `, this makes the routes inclusive, which means if a path can match two routes, both components will render. See full detail here: https://medium.com/@djoepramono/react-router-4-gotchas-2ecd1282de65
    – Nah Oct 18 '17 at 12:42
  • 1
    But I cannot have `history={history}` when using BrowserRouter, so I am not sure how is this the solution :/ – OFFLlNE Mar 13 '19 at 17:20
20

Which version of React Router are you using? Router version 4 changed from passing in the browserHistory class to passing an instance of browserHistory, see the code example in the new docs.

This has been catching lots people who automatically upgrade; a migration document will be out 'any day now'.

You want to add this to the top:

import { createBrowserHistory } from 'history'

const newHistory = createBrowserHistory();

and

<Router history={newHistory}/>
Albert Dugba
  • 85
  • 1
  • 9
Charles Merriam
  • 19,908
  • 6
  • 73
  • 83
4

If you want to have multiple routes you can use switch like this,

import {Switch} from 'react-router'; 

then

<BrowserRouter>
     <Switch>
         <Route exact path="/" component={TodoComponent} />
         <Route path="/about" component={About} />
     </Switch>
</BrowserRouter>
Saurabh Narhe
  • 189
  • 1
  • 10
3

I got the same problem in ES6, but when I switched to use 'react-router-dom' library, the problem was solved. For all fans of ES6, here we go:

npm install --save react-router-dom

In index.js:

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

ReactDOM.render(
    <HashRouter>
        <Route path="/" component={App}/>
    </HashRouter>
  ,
  document.getElementById('root')
);
maxadorable
  • 1,290
  • 1
  • 10
  • 24
Dimang Chou
  • 595
  • 6
  • 9
1

Version 4 of React Router changed several things. They made separate top level router elements for the different history types. If you're using version 4 you should be able to replace <Router history={hashHistory}> with <HashRouter> or <BrowserRouter>.
For more detail, see https://reacttraining.com/react-router/web/guides

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
jack.lin
  • 15
  • 5
1

For (year 2022) version "react-router-dom": "^6.3.0" if anyone is still facing this issue check the order of import in App.js file.

import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

I don't know why the order matters but it worked for me.

Also this might help: Attempted import error: 'Switch' is not exported from 'react-router-dom'

JavaQuest
  • 671
  • 6
  • 23
0

I also write a Login practice. And also meet the same question like you. After a day struggle, I found that only this.props.history.push('/list/') can make it instead of pulling in a lot of plugins. By the way, the react-router-dom version is ^4.2.2. Thanks!

handleSubmit(e){
    e.preventDefault();
    this.props.form.validateFieldsAndScroll((err,values)=>{
        if(!err){
            this.setState({
                visible:false
            });
            this.props.form.resetFields();
            console.log(values.username);
            const path = '/list/';
            this.props.history.push(path);
        }
    })
}
YangFang
  • 3
  • 1
0

The below works for me with "react-router@^3.0.5":

package.json:

"react-dom": "^16.6.0",
"react-router": "^3.0.5"

index.js:

import { render } from 'react-dom'
import { App } from './components/App'
import { NotFound404 } from './components/NotFound404'
import { Router, Route, hashHistory } from 'react-router'

render(
    <Router history={hashHistory}>
        <Route path='/' component={App} />
        <Route path='*' component={NotFound404} />
    </Router>,
    document.getElementById('root')
)