First, thank you for creating and maintaining this incredibly useful library.
I'm having trouble getting scroll position to reset to the top of a page on navigation in RC1. My code looks something like the following:
var indexComponent = React.createClass({
render() {
return (
<div>
{this.children}
</div>
)
}
});
var componentOne = React.createClass({
mixins: [History],
handleClick() {
this.history.pushState(null, '/route-two')
},
render() {
return (
<div>
<a onClick={this.handleClick}>
Link to Component 2
</a>
</div>
)
}
});
var componentTwo = React.createClass({
mixins: [History],
handleClick() {
this.history.pushState(null, '/route-one')
},
render() {
return (
<div>
<a onClick={this.handleClick}>
Link to Component 1
</a>
</div>
)
}
});
var routeConfiguration = {
path: "/",
indexRoute: {
component: indexComponent
},
childRoutes: [
{
path: "route-one",
component: componentOne,
onEnter: doSomeAuthStuff,
ignoreScrollBehavior: true
},
{
path: "route-two",
component: componentTwo,
onEnter: doSomeAuthStuff,
ignoreScrollBehavior: true
}
]
};
React.render(
<Router history={browserHistory} routes={routeConfiguration} />,
document.getElementById('app')
);
Am I using the wrong part of the API to reset scroll position to the top of the page? If so, what's the proper way to trigger that behavior?
See #1958 However, setting the scroll position onUpdate as suggested didn't work for me for no comprehensible reason. I had to put it in the onEnter hook (which isn't nice but works for my case) :/
as @kaikuchn mentioned, use onUpdate:
<Router onUpdate={() => window.scrollTo(0, 0)} history={createBrowserHistory()}>
...
</Router>
Using onUpdate didn't quite work out for me because I wanted to "preserve scroll position when using the back button, scroll up when you come to a new page".
Maybe onUpdate should have location passed to its arguments?
The workaround I found was this:
var history = createBrowserHistory();
history.listen(location => {
// Use setTimeout to make sure this runs after React Router's own listener
setTimeout(() => {
// Keep default behavior of restoring scroll position when user:
// - clicked back button
// - clicked on a link that programmatically calls `history.goBack()`
// - manually changed the URL in the address bar (here we might want
// to scroll to top, but we can't differentiate it from the others)
if (location.action === 'POP') {
return;
}
// In all other cases, scroll to top
window.scrollTo(0, 0);
});
});
var routes = (
<Router history={history}>
// ...
</Router>
);
Here's my slightly modified hack to scroll to a URL fragment if it exists
history.listen(location => {
// Use setTimeout to make sure this runs after React Router's own listener
setTimeout(() => {
// Keep default behavior of restoring scroll position when user:
// - clicked back button
// - clicked on a link that programmatically calls `history.goBack()`
// - manually changed the URL in the address bar (here we might want
// to scroll to top, but we can't differentiate it from the others)
if (location.action === 'POP') {
return;
}
// In all other cases, check fragment/scroll to top
var hash = window.location.hash;
if (hash) {
var element = document.querySelector(hash);
if (element) {
element.scrollIntoView({block: 'start', behavior: 'smooth'});
}
} else {
window.scrollTo(0, 0);
}
});
});
@kjs3 We're actively discussing this on #2471 and the associated issue. Would appreciate your feedback there since you've obviously put some thought into this.
@taion Ok cool, I'll test it out and let you know over there.
Most helpful comment
Using
onUpdatedidn't quite work out for me because I wanted to "preserve scroll position when using the back button, scroll up when you come to a new page".Maybe
onUpdateshould havelocationpassed to its arguments?The workaround I found was this: