Search code examples
javascriptiosiphonereactjsmobile-safari

Mobile Safari IOS will scroll bottom page automatically when reloading page


I'm using react and as soon as I reloading page on safari it will scroll automatically at the bottom of the page for no reason. This bug appears only using Iphones.

I'm struggling to find where this bug comes from but I have no clue.

the only solution I found is :

componentDidMount() {
  setTimeout(() => {
    window.scrollTo(0, 0);
  }, 800); 
}

Using window.scrollTo(0, 0)in componentDidMount() has no effect except if I'm using setTimeout, but I don't know think this is right way to do it..

When I'm clicking on link from the App I have no problems since I'm using this method https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/guides/scroll-restoration.md


Solution

  • I finally found why I had this bad behavior on Safari Mobile.

    In my app I have a component AppContainer which encapsulate all my routes

    routes.js

     <AppContainer location={window.location}>
        <Switch>
            <Route path="/sign-in" component={SignInContainer} />
        </Switch>
    </AppContainer>
    

    in which, I export default my class export default withRouter((connect(mapStateToProps, mapDispatchToProps)(AppContainer)));

    It turns out that in this component, componentDidMount()was called before all the nested component in my routes. first problem I solved by adding translatein my export default.

    Because I'm using react-i18next with options react: { wait: true }, all nested children components have export default translate(['common')).

    that means every time a child is mounted it will wait to load all locales before the rendering, which is not the case with AppContainerthat's why his componentDidMount was called first.

    I just needed to add

    export default withRouter( translate([])(connect(mapStateToProps, mapDispatchToProps)(AppContainer)), );

    Now the lifecycle was fixed, I just need to add scrollBy on the componentDidMountin AppContainer and this time I used

    AppContainer

      componentDidMount() {
        setTimeout(() => {
            window.scrollTo(0, -5000);
        }, 0);
      }
    

    and not an approximately time out of 800ms.

    Hope it will help people who encounter the same issue.