question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using Browser buttons, gets rendered page out of sync with path

See original GitHub issue

My routing seems to work fine. But when I use the browser ‘back’ button, the URL changes correctly, but the page then doesn’t match the URL. The first time I hit the back button, nothing happens. Then second time I click it goes to where it should have gone the first time.

This is my entry point: index.tsx:

 {UserStore} from './data/stores/UserStore';
declare let module: any;

import * as React from "react";
import * as ReactDOM from "react-dom";
import {AppContainer} from 'react-hot-loader';
import { Router } from 'react-router';
// import createHistory from 'history/createBrowserHistory';
import createHistory from 'history/createHashHistory';
import { Provider } from 'mobx-react';
import { RouterStore, syncHistoryWithStore } from 'mobx-react-router';
import { App } from "./components/app/App";

const history = createHistory();
const routingStore = new RouterStore();
const users = new UserStore();
const synchronizedHistory = syncHistoryWithStore(history, routingStore);
const stores = {
    routing: routingStore,
    users: users
};

const renderApp = (Component: any) =>
{
    ReactDOM.render(
        <AppContainer>
            <Provider {...stores}>
                <Router history={synchronizedHistory}>
                    <Component />
                </Router>
            </Provider>
        </AppContainer>,
        document.getElementById("app_content")
    );
};

renderApp(App);

// Hot Module Replacement API
if (module.hot) {
    module.hot.accept('./components/app/App', () => {
        renderApp(App)
    });
}

My app file:

import 'bootstrap';
import * as React from 'react';
import {TopNav} from '../topnav/TopNav';
import {History} from 'history';
import {Routes} from './Routes';
import {inject, observer} from 'mobx-react';
import {UserStore} from '../../data/stores/UserStore';
import {Level, Logger} from '../../util/Logger';

interface IAppProps { routing: History, users: UserStore }

@inject('routing')
@observer
export class App extends React.Component<IAppProps, undefined>
{
    //noinspection JSMethodCanBeStatic,JSUnusedLocalSymbols
    private log(msg: string, level?: Level): void
    {
        Logger.get().log(msg, 'App', level || Level.TRACE);
    }

    render(): JSX.Element
    {
        const { location } = this.props.routing;
        return (
            <div>
                <TopNav/>
                <div className='container body-content'>
                    <Routes/>
                    <div className='small'>path: {location.pathname}</div>
                </div>
            </div>);
    }
}

My routes file:

import * as React from 'react';
import {Route, Switch} from 'react-router-dom';
import {HomePage, PageOne, PageThree, PageTwo} from '../home/HomePage';
import {PendingDeliveryPage} from '../delivery/PendingDeliveryPage';
import {DeliveryExecutePage} from '../delivery/DeliveryExecutePage';


export class Routes extends React.Component<undefined, undefined>
{
    public render(): JSX.Element
    {
        return (
            <Switch>
                <Route exact path='/' component={HomePage} />
                <Route path='/delivery/:id/execute' component={DeliveryExecutePage} />
                <Route path='/delivery' component={PendingDeliveryPage} />
                <Route path='/one' component={PageOne} />
                <Route path='/two' component={PageTwo} />
                <Route path='/three' component={PageThree} />
            </Switch>
        );
    }
}

And lastely my test pages:

import * as React from "react";
import {Link, RouteComponentProps} from 'react-router-dom';

export class HomePage extends React.Component<RouteComponentProps<any>, undefined>
{
    public render(): JSX.Element
    {
        return (
            <div>
                <h1>Home</h1>
                <ul>
                    <li><Link to="/">Home</Link></li>
                    <li><Link to="/one">One</Link></li>
                    <li><Link to="/two">Two</Link></li>
                    <li><Link to="/three">Three</Link></li>
                </ul>
            </div>);
    }
}

export class PageOne extends React.Component<RouteComponentProps<any>, undefined>
{
    public render(): JSX.Element
    {
        return (
            <div>
                <h1>Page One</h1>
                <ul>
                    <li><Link to="/">Home</Link></li>
                    <li><Link to="/one">One</Link></li>
                    <li><Link to="/two">Two</Link></li>
                    <li><Link to="/three">Three</Link></li>
                </ul>
            </div>);
    }
}

export class PageTwo extends React.Component<RouteComponentProps<any>, undefined>
{
    public render(): JSX.Element
    {
        return (
            <div>
                <h1>Page Two</h1>
                <ul>
                    <li><Link to="/">Home</Link></li>
                    <li><Link to="/one">One</Link></li>
                    <li><Link to="/two">Two</Link></li>
                    <li><Link to="/three">Three</Link></li>
                </ul>
            </div>);
    }
}

export class PageThree extends React.Component<RouteComponentProps<any>, undefined>
{
    public render(): JSX.Element
    {
        return (
            <div>
                <h1>Page Three</h1>
                <ul>
                    <li><Link to="/">Home</Link></li>
                    <li><Link to="/one">One</Link></li>
                    <li><Link to="/two">Two</Link></li>
                    <li><Link to="/three">Three</Link></li>
                </ul>
            </div>);
    }
}

You can click

  1. Start at ‘Home’
  2. Click ‘One’
  3. Click ‘Two’
  4. Click ‘Three’, and everthing should be fine.
  5. Click Browser Back, path changes to /two, but page does not render anything new.
  6. Click Browser Back and path changes to /one, and now page /two renders.
  7. Click Browser Back and page changes to /, but page /one renders.
  8. etc.

Am i doinng something wrong here?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:20 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
alisd23commented, May 30, 2017

Ok after more investigating it looks like a react-router problem, but not with the switch - with the Route component update. The Route component uses context to get the current location, and I think the shouldComponentUpdate of the mobx-react observer component (which wraps App in your example) is returning false. This in turn is messing up the context update.

Context is known to be a fairly broken feature, especially when pairing with MobX/Redux, which overwrite shouldComponentUpdate in places.

This needs bringing up with the react-router guys.

In terms of a workaround - wrapping App (the component which uses mobx observer) in withRouter from react-router works for me, as this will overwrite the shouldComponentUpdate from observer.

1reaction
wallynmcommented, Sep 4, 2018

Sory about bring this discussion again, turns out that i’ve discovered a problem that i had im my configuration and this may help someone!

Once you create the History with synced Store, you don’t need the React Router <BrowserRouter> component

const History = syncHistoryWithStore(browserHistory, Stores.RouterStore);

You just initialize with <Router history={History}> and you’re ready to register and access your routes. My problem was caused by a duplicated initialization of the BrowserRouter in the startup React component:

class App extends Component {
  render() {
    return (
      <Provider {...Stores}>
         /** You only need this Router to the React Router work, and the routes of course */
        <Router history={History}>
          /** Problem was caused by this duplicated routing control */
          <BrowserRouter>
            <Routing/>
          </BrowserRouter> /** Root of my problem - duplicated routing control */
        </Router>
      </Provider>
    )
  }
}

I had <Router={history}> and also <BrowserRouter>, together only the last one was working and it was breaking the plugin functionality. After removing BrowserRouter with only <Router history={History}> solved my issue!

Was a silly mistake because once you learn how to configure V4 routing and you plug this package into your app everything works fine, but turns out that two Routing are trying to control the app state and just the last one work breaking the package functionality.

Well, at the end just removing BrowserRouter and let the plugin do his job with syncHistoryWithStore solved my issues! Thanks.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Keep browser URL in sync with application status
1. I have found no way to do this in Angular ·.route(url) will reload the page ·.url(url) will reload the page ·.go(..) will...
Read more >
React Router DOM: How to handle routing in web apps
Let's say we encounter a nonexistent route/path in our app. Instead of letting the browser show an error, we can customize a 404...
Read more >
React Router v5: The Complete Guide - SitePoint
Routing is the process of keeping the browser URL in sync with what's being rendered on the page. React Router lets you handle...
Read more >
The Most Complete Guide for React Navigation - CopyCat Blog
Whenever you want to use URL in your application, routing comes into play. In this tutorial, we will explore routing or React navigation....
Read more >
Tutorial v6.6.1 - React Router
And with that, we're ready to get started! ... Open it up and we'll put React Router on the page. Create and render...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found