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.
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
Most helpful comment
@crazy4groovy You just need to create a module that exports the
historyobject for your application.Anywhere that you want to reference it, you just import it.