react-router v4 - browserHistory is undefined

2020-01-31 03:16发布

问题:

I am creating my first react app in electron (my first electron app too). I have two routes & need to navigate from one to another. For that I am using following code:

Root

ReactDOM.render(
  <Router history={browserHistory}>
      <App />
  </Router>,
  document.getElementById('root')
);

App

class App extends React.Component {
    constructor() {
        super();
    }
    render() {
        return (
            <div className="app-master">
                <Switch>
                    <Route path='/city' component={CityList}/>
                    <Route path='/' component={SplashScreen}/>
                </Switch>
            </div>
        )
    }
}

Page

import { browserHistory } from 'react-router';
...
browserHistory.push('/city');

This line gives error,

TypeError: Cannot read property 'push' of undefined

I searched web for possible solution but can't find one! There are many similar questions on SO too, but none of it worked for me :(

回答1:

You have to import it from the history module now which provides 3 different methods to create different histories.

  • createBrowserHistory is for use in modern web browsers that support the history API
  • createMemoryHistory is used as a reference implementation and may also be used in non-DOM environments, like React Native or tests
  • createHashHistory for legacy web browsers

You cannot use the browser history in an electron environment, use the hash or the memory one.

import { createHashHistory } from 'history'

const history = createHashHistory()

You can then use the history injected in the props

this.props.history.push('/')


回答2:

Its is not working for your because in your component you are still using browserHistory which is not longer availabe from react-router package. You should change to using history from the history package

To simplify you can create a history.js file with the following contents

import { createBrowserHistory } from 'history'

export default createBrowserHistory();

Root

import history from '/path/to/history';

ReactDOM.render(
  <Router history={history}>
      <App />
  </Router>,
  document.getElementById('root')
);

Page

import history from 'path/to/history';
...
history.push('/city');


回答3:

Useful pointers above. The simplest solution I've found is to add:

import {createBrowserHistory} from 'history';

to your list of import statements, then add:

const browserHistory = createBrowserHistory();

Might not work perfectly, but for the basic stuff I'm working on seems to do the trick. Hope that helps.



回答4:

import { browserHistory } from 'react-router' does not work in React router 4. Link

Use the redirect component:

import { Redirect } from 'react-router';
<Redirect push to="/somewhere/else"/>

The render function should replace the entire content with Redirect component.



回答5:

In react-router v4 initialize router as constant config and access the history through this.props in child components.

Import you dependecies

import { Route, Router } from "react-router";
import { createBrowserHistory } from "history";

Define your router config and add history as prop

const history = createBrowserHistory();
const routes = (
  <Router history={history}>
    <Route path='/city' component={CityList}/>
    <Route path='/' component={SplashScreen}/>
  </Router> )

class App extends Component {
  render() {
    return ( 
    <div className = "app-master> 
      {routes} 
    </div>)
}

Defining route as a constant and out of render method this would initialize the route config only once.

Page Component

class Page extend Component {
  render() {
    this.props.history.push('/');
  }
}

The history is now available as props in all the child components defined in routes config.