Reputation: 9492
Using react-router I'm looking for a way to update the page URL / hash, without the router re-rendering the whole page.
I am developing a full page carousel, and would like each slide to have it's own URL (allowing the user to refresh the page and return to the correct slide). The carousel will later have swipe similar to this demo, which means the next slide is pre-rendered.
A stripped down version of my carousel is available here.
The current slide change looks like this:
onClickLeft: function() {
this.setState({
selected: this.state.selected - 1
});
}
This works fine, with no URL updates. What I really want is:
mixin: [Navigation],
onClickLeft: function() {
this.transitionTo('carousel-slide', {num: this.state.selected + 1});
}
This would set the prop of the current slide, allowing the carousel to animate. However using this method now causes the page to re-render and no animation is displayed.
I have seen the ReactCSSTransitionGroup
used for route transitions, however this seems geared toward rendering a new page and transitioning out the old one.
If there's already a way to achieve what I'm looking for, and I've missed it, could someone point me in the right direction?
Upvotes: 35
Views: 55962
Reputation: 804
React Router v6
JavaScript
If you really want to do this with React Router, you can look at some workarounds in this issue or look at the HTML solution below. However, I would just recommend doing it using the window object.
If you want it plain and simple, set the hash like this:
window.location.hash = '#newHash'
.
If you don't want to push something to the history stack, use window.location.replace
, like in the following example:
window.location.replace('#newHash')
.
HTML (<Link>
)
Use an anchor tag, if you only want to link to a hash, and you don't need any React Router features.
If you just want to create a <Link to="">
element, you can set reloadDocument
to true, like in the following example:
<Link reloadDocument to="#test"></Link>
. This skips client side routing and lets the browser handle the transition normally as it were an anchor tag. Read more about it here. Make sure React Router renders the to="[this link]"
link correctly! If you want, like me, that the hash will not get pushed to the user's history, you also need to set the replace
attribute on the link element to true. However, this solution does not work, if you have search parameters.
Upvotes: 4
Reputation: 3962
For React router v4 you need to use history
and pass it as prop to the Router
. Router
will then pass history
object to your component as a prop and you can use it like so:
// In your component
this.props.history.push("#testing")
History file
// history.js
import createHistory from "history/createBrowserHistory";
export default createHistory();
Then, wherever you are declaring your router, pass the history prop
import history from "./history";
import { Router } from "react-router-dom";
<Router history={history}>
// ... Your component
</Router>
Upvotes: 6
Reputation: 14790
It is a pain to work with react-router because it involves breaking changes in every major and minor release
React Router v2.0 rc5
import { hashHistory } from 'react-router'
this.props.location.query.t = key;
hashHistory.replace(this.props.location);
Upvotes: 11
Reputation: 86220
react-router no longer sets a key on your routes. If you do need to set a key from a route handler, put it on a surrounding element.
return (
<div key={this.props.params.bookId}>
{this.props.children}
</div>
);
It's now <ReactRouter.RouteHandler key="anything" />
, but this is also no longer really needed due to changes in react-router. See the changelog for more details.
Currently, react-router sets a key on your handler based on the current route. When react does its diff, and notices a different key, it throws out the entire subtree both in virtual and real dom, and rerenders.
To prevent this, you can override react-router's key when using activeRouteHandler()
this.props.activeRouteHandler({key: "anything"})
Upvotes: 12