React-router: Redirect using history in actioncreator and react-router v.4

Created on 1 Apr 2017  路  7Comments  路  Source: ReactTraining/react-router

Hi, I'm trying to navigate programmatically in action creator after calling an API and receiving a response.
What I did:
I created a file utils/History.js with this code:
import createBrowserHistory from 'history/createBrowserHistory'; export default createBrowserHistory();

and then used it in action creator:
import History from '../../utils/History'; //some code// History.replace('/sign-in');
Of course, I let relevant component know about this routing. If I use <NavLink to='/sign-in'>, it works.
But if I want to render this component on History.replace('/sign-in') or History.push('/sign-in'), I can see just 'localhost:8080/sign-in' in addressbar, but relevant component doesn't appear.
Perhaps, is there a 'true' React way to achieve it?
Please help me to figure out.

Most helpful comment

@crazy4groovy You just need to create a module that exports the history object for your application.

// history.js
import createHistory from 'history/createHashHistory';
export default createHistory();

Anywhere that you want to reference it, you just import it.

// index.js
import { Router } from 'react-router-dom';
import history from './history';

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder);

All 7 comments

Does your router use the same history object?

@pshrmn Yes. I use it lilke this.
Inside the main file app.js:

import History from './utils/History';

ReactDOM.render(
  <BrowserRouter history={History}>
    <App />
  </BrowserRouter>,
  document.getElementById('app'));

And this is the code inside App component:

import History from '../../utils/History';

let loggedIn = localStorage.getItem('token');

loggedIn ? History.replace('/dashboard') : History.replace('/sign-in');

class App extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div className='height-100'>
        <Header />
        {this.props.children}
    <Route path='/sign-in' render={() => (
      loggedIn ? (
        <Redirect to="/dashboard" />
      ) : (
        <SignIn />
      )
    )} />
    <Route path='/sign-up' render={() => (
      loggedIn ? (
        <Redirect to="/dashboard" />
      ) : (
        <SignUp />
      )
    )} />
      </div>
    );
  }
}

You cannot pass a history to <BrowserRouter>. It creates its own history object. If you are using your own history object, you should use the base <Router> component.

Import { Router } from 'react-router-dom'

Side note: I had to edit your comment to actually see your code. Please check out this article to see how to format multi-line code blocks. https://help.github.com/articles/creating-and-highlighting-code-blocks/

@pshrmn Thanks bro, you saved my day! Works like a charm :)

You cannot pass a history to . It creates its own history object.

Is there a way to access/expose its created history object? So that it can be used to navigate _programmatically_ in an action creator? It was SUPER convenient in v3 to do:

import { hashHistory } from 'react-router';

. . . .
   // inside a saga
   hashHistory.push('/');

Note: I see some reference to history in the docs here: https://reacttraining.com/react-router/web/example/auth-workflow
but getting to it via withRouter seems more awkward then it needs for non-react-specific (i.e. business logic) code.

@crazy4groovy You just need to create a module that exports the history object for your application.

// history.js
import createHistory from 'history/createHashHistory';
export default createHistory();

Anywhere that you want to reference it, you just import it.

// index.js
import { Router } from 'react-router-dom';
import history from './history';

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder);

Like @crazy4groovy wrote, solution for problem with changing url path but not the requested component is change: import { BrowserRouter as Router } from 'react-router-dom';
to: import { Router } from 'react-router-dom in index.js

Was this page helpful?
0 / 5 - 0 ratings