jbrown
jbrown

Reputation: 7996

React router redirects - pushState on the same or a different history object?

I'm trying to perform a redirect in a react component using react-router 1.0.2.

In my main app.js I create a hash history:

import createHashHistory from 'history/lib/createHashHistory';
const history = createHashHistory();
...
ReactDOM.render(
    <RelayRouter history={history} routes={routes} />,
    document.getElementById('root')
);

When I perform a database insert, I want to redirect to another page. I was using this which worked in an earlier version, but doesn't work any more:

import createHashHistory from 'history/lib/createHashHistory';
const history = createHashHistory();
...
// inside Component after a successful DB insert
  history.pushState(null, `/#/albums/${newAlbum.id}`, null);

This is in another component (CreateAlbum).

Do I need to call pushState on the same history instance, and if so how can I get hold of it from within a component? If not, what am I doing wrong? The location bar does get updated, but the page stays the same.

Finally, I've manually prefixed /#/ to the URL. This is sloppy and will only work with a Hash History. I saw in the API there's a createHref method, but it expects a pathname which isn't explained. Given that the relevant route is defined as follows, how can I use that to generate a URL in the correct form as well?

<Route
  component={App}
  queries={ViewerQueries}
  path="/">
  <Route
    path="/create" component={CreateAlbum} />
  <Route
    path="/albums/:albumId" component={AlbumDetails}
    queries={ViewerQueries} />
</Route>

Upvotes: 3

Views: 11890

Answers (2)

DaxChen
DaxChen

Reputation: 1909

You have to call it on the same history instance.

If you're calling it in the Route components you defined in the component props of Route, such as your App, CreateAlbum or AlbumDetails, the history object is already available as this.props.history, you can console.log(this.props.history) to check it!

So you can simply call:

this.props.history.pushState(null, `/#/albums/${newAlbum.id}`)

to change route.

But if you want to call it in a nested component, you can...

Pass the history as a prop all the way down to your component:

<NestedComponent history={this.props.history} />

Use the history mixin if you're using react-router 1.0.2 (deprecated after 1.0.3)

checkout this SO for more detail

Use the router context's push method if you're using 1.0.4


If your component isn't really deep down, passing the history as prop might be easier!

Upvotes: 6

Nathan
Nathan

Reputation: 26

To expand on Dax's answer,

The Router will pass the history component down to its nodes as a prop - hence this.props.history will be available on all your Route nodes. You shouldn't need to create a new history object for each component.

If you create a non-route component, you will need to pass the history into that component as Dax mentioned or pass some sort of relevant 'event' function from history as passing the entire object might not be totally necessary.

If you're already on 1.0.x - rackt has just released the rc for 2.0.0 as well which should be a fairly smooth upgrade. You can check out the upgrade guide here

Upvotes: 0

Related Questions