Skip to content

Scroll position in RC1 #2144

@msouce

Description

@msouce

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?

Activity

kaikuchn

kaikuchn commented on Sep 30, 2015

@kaikuchn

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) :/

knowbody

knowbody commented on Sep 30, 2015

@knowbody
Contributor

as @kaikuchn mentioned, use onUpdate:

<Router onUpdate={() => window.scrollTo(0, 0)} history={createBrowserHistory()}>
  ...
</Router>
nicolashery

nicolashery commented on Oct 25, 2015

@nicolashery

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>
);
kjs3

kjs3 commented on Nov 4, 2015

@kjs3

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);
    }
  });
});
taion

taion commented on Nov 4, 2015

@taion
Contributor

@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.

kjs3

kjs3 commented on Nov 4, 2015

@kjs3

@taion Ok cool, I'll test it out and let you know over there.

locked as resolved and limited conversation to collaborators on Jan 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @kjs3@kaikuchn@msouce@nicolashery@taion

        Issue actions

          Scroll position in RC1 · Issue #2144 · remix-run/react-router