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
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 translate
in 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 AppContainer
that'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 componentDidMount
in 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.