-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does it support react-router v4 ? #52
Comments
No. RRv4 has no concept of router middlewares. |
Are there plans for something like this to be built for v4? |
I do not plan to do so, no. |
I have forked this repo to support React Router v4. The result is here : https://github.com/ytase/react-router-scroll Minor adjustements were required (like saving the data in sessionStorage instead of the state of history). I added some doc in the Readme and warning. The library seems to be working as expected, but I haven't taken time to fix the tests yet. Anybody is obviously free to use my fork to have that great library working under React Router 4, and help bringing something more solid into life (fixing tests, maybe changing some other things in the code etc.). I can also create a pull request if you are interested, though it is still pretty early for that. |
@mijamo I'm curious why you needed to change the storage backend. |
As you can see here https://github.com/taion/react-router-scroll/blob/master/src/StateStorage.js the storage backend was using React Router v4 uses the new version of Maybe a next step would be to use something like https://github.com/nbubna/store which is widely used for that kind of problem. |
Isn't that implementation going to do weird things when there are redirects? |
I have not tried yet, I do not use redirects with react router. As I said it is very early, I just wanted to share my early experiment in case anybody is interested. For now it is working good when I test it but there are tons of improvements possibles and that would be needed to have something ready to be published and widely used. What is your intuitive thought regarding redirects and in which situation would they cause trouble? |
RRv4 re-renders the page on a redirect, right? so it will try to scroll the page. also render a blank page (ish) and mess up any saved scroll position |
I tried quickly with a Redirect and did not encounter the problem you are suggesting. When finding a So let's say you are at Or have I misunderstood what you meant? |
The issue I'm thinking of is that, if you click on a link that redirects you, the scroll update will fire twice – once on the page that renders the redirect, then once on the page you actually want to get to. It may well not leave anything broken, but I think it could look janky, especially if the scroll destination is a hash anchor or partway down the page or something. |
Unfortunately
The I.e. this: https://github.com/ReactTraining/history/blob/master/modules/createBrowserHistory.js#L172 is called before this: https://github.com/ReactTraining/history/blob/master/modules/createBrowserHistory.js#L183 It's the same for So that means when you return to the page and the To be clear, I'm talking about the lesser used component for when you want scrollable elements, not the However, the patch here (affecting window) may have broken as well: But I've yet to have that issue so I can't test it. ps. It's the reason the original |
A hacky solution I've been playing with is keeping a record of the previous |
@faceyspacey You seem to know |
@mijamo working on upgrading Gatsby to use RRv4 and dropped your fork in and after some basic testing seems to be working great! Will be testing more and contributing back if needs be. Perhaps we should turn your fork into a real project? Or @taion would you be interested in letting us use this repo for the v4 version of this module? |
@halt-hammerzeit will do. @KyleAMathews basically, the issues mentioned here should probably be fixed before it becomes its own repo. I actually made a repo for a reworking of this for redux-first-router: https://github.com/faceyspacey/redux-first-router-restore-scroll I fixed 2 of the 3 issues, but can't replicate the one i mentioned above. ..and ultimately 1 of the issues doesn't apply to The hard part really is React Router will need to expose a |
I'd be okay with merging the RRv4 bits, assuming the outstanding issues are resolved. |
What's that status of this? Should folks move to the fork? |
If it's working for everyone, we can merge it, I guess. I'd rather the issues here be addressed, but probably if it works in practice, the theoretical issues are not so big a deal. |
Here's a draft of an approach that I'm using. I haven't read the To use it just import and call import { browserHistory } from 'react-router';
export const scrollMemory = () => {
const ATTEMPT_RESTORE_MILLISECONDS = 500;
const REATTEMPTS_TO_SCROLL = 10;
const memory = {};
let wasUserGeneratedScroll = true;
const getScrollTop = () => {
if (document.body && document.body.scrollTop) {
return document.body.scrollTop;
} else if (document.documentElement && document.documentElement.scrollTop) {
return document.documentElement.scrollTop;
}
return 0;
};
const stringifyLocation = (location) => {
return `/${location.pathname.replace(/^\//, '')}${location.search
? `?${location.search.replace(/^\?/, '')}`
: ''}${location.hash ? `#${location.hash.replace(/^#/, '')}` : ''}`;
};
window.addEventListener('scroll', () => {
const location = browserHistory.getCurrentLocation();
const url = stringifyLocation(location);
memory[url] = getScrollTop();
// if they're currently in the middle of attempting
// to restore a scroll position...
if (restoreScrollTimer && wasUserGeneratedScroll) {
// the user has scroll themselves during attempting
// to restore scroll positions so cancel further attempts
clearTimeout(restoreScrollTimer);
}
});
let restoreScrollTimer;
const eventuallyScrollTo = (scrollTop) => {
if (restoreScrollTimer) {
clearTimeout(restoreScrollTimer);
}
let remainingAttempts = REATTEMPTS_TO_SCROLL;
const attemptScroll = () => {
remainingAttempts--;
wasUserGeneratedScroll = false;
window.scrollTo(0, scrollTop);
requestAnimationFrame(() => {
wasUserGeneratedScroll = true;
});
if (remainingAttempts > 0 && getScrollTop() !== scrollTop) {
restoreScrollTimer = setTimeout(
attemptScroll,
ATTEMPT_RESTORE_MILLISECONDS
);
}
};
attemptScroll();
};
browserHistory.listen(location => {
// fired when the browser changes urls
const url = stringifyLocation(location);
if (memory[url]) {
// there's been a url change and we have a new scroll
// position to restore
eventuallyScrollTo(memory[url]);
}
});
}; |
I'm sharing my current solution, as I think it's quite nice and I haven't seen it elsewhere in this form (using react-router location state). It defaults to scrolling to the top on location change (and lets the browser handle "Back" and "Forward" scroll state -- which I've tested to work well in Firefox & Chrome newest versions). It also allows for you to change location without resetting on a case by case basis, using react-router's location state. // ScrollToTop.js
import React from 'react';
import { withRouter } from 'react-router-dom';
class ScrollToTop extends React.Component {
componentDidUpdate(prevProps) {
if (prevProps.location && this.props.location !== prevProps.location &&
!(this.props.location.state && this.props.location.state.resetScroll === false)) {
window.scrollTo(0, 0);
}
}
render() {
return this.props.children;
}
}
export default withRouter(ScrollToTop); // client.js
...
<ScrollToTop>
<App />
</ScrollToTop>
... // Example usage:
history.push('/about'); // Reset the scroll
history.push('/tab/1', { resetScroll: false }); // Don't reset the scroll |
For the time being, why not just use @ytase's |
@ytase Can you update to use new context instead of legacy? |
No description provided.
The text was updated successfully, but these errors were encountered: