Search code examples
androidcordovareactjsreact-routerrefluxjs

React-Router component unmounting on transition


I'm using React-Router to navigate my mobile app. For some reason my components are unmounting on every transition and then remounting on "back". This results in lost state and lost scroll position. I'm not doing "ignoreScrollPosition" anywhere so I'm puzzled as to what may be causing this.

I'm using Reflux to manage my state and writing an app for mobile phones using Cordova/Phonegap. Has anyone run into trouble with this using Cordova/Phonegap before?

Here's the code I'm using for the router:

var React = require('react');
var Reflux = require('reflux');
var Router = require('react-router');
var Route = Router.Route;
var DefaultRoute = Router.DefaultRoute;
var RouteHandler = Router.RouteHandler;

var App = React.createClass({
    render: function () {
        return (
            <RouteHandler/>
        );
    }
});

...

var routes = (
    <Route handler={App} path="/">
        <DefaultRoute handler={LaunchScreen} />
        <Route name="sample" path="/sample" handler={SampleScreen} />
        ...
    </Route>
);

Router.run(routes, function (Root) {
    React.render(<Root/>, document.body);
});

Solution

  • It turns out the problem was related to my use of Flexbox. My body wasn't scrolling, instead an element inside it was.

    My flexbox UI looked like this:

    +----------------+
    |    .header     |
    +----------------+
    |                |
    |    .content    |
    |                |
    +----------------+
    |    .footer     |
    +----------------+
    
    body {
         display: flex;
         flex-direction: column;
         ...
    }
    .content {
         flex: 1;
         overflow-y: auto;
         ...
    }
    

    This meant that the .content element was scrolling instead of the document body. It seems React-Router keeps track of the scroll position of the document body.

    So, to fix this I used position: fixed for the .header and .footer and abandoned using flexbox to render the core UI in this way. As a result, the document body scrolls now and React-Router keeps track of it.

    As an added benefit, the browser seems a lot more performant during paints.