Shopify App Bridge and React Router

I recently started building Shopify apps and ran into a problem with an embedded app and getting the URL change to reflect in the browser. The iframe would update, and I would be on the page, but the URL in the browser wouldn’t update. While not a critical feature, it’s sure annoying if you refresh the page and you can’t get the exact page on because instead of /orders/10 the URL only shows /orders/.

I spent hours researching how to do it, and found either out-of-date comments or things half done.

The not so obvious RoutePropagator is what you are looking for. After following the setup for the ClientRouter, the missing piece was adding in the RoutePropagator where I define my main <Switch> and <Route> statements.

//App.jsx
import { useRoutePropagation } from '@shopify/app-bridge-react';

function App({ location }) {
    //the magic was right here
    useRoutePropagation(location);

    return (
      <Switch>
          <Route path="/settings" component={Settings} />
          <Route path="/plan" exact component={Plan} />
          <Route path="/" exact component={Dashboard} />
      </Switch>
  );
});
//AppRouter.js
import {withRouter} from 'react-router'
import {useClientRouting} from '@shopify/app-bridge-react';
//Setup with the ClientRouter hook
function AppRouter(props) {
    const {history} = props;
    useClientRouting(history);
    return null;
}

export default withRouter(AppRouter);
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter, Link } from 'react-router-dom'
import { Provider as AppBridgeProvider } from '@shopify/app-bridge-react'
import enTranslations from '@shopify/polaris/locales/en.json';
import {AppProvider as PolarisProvider} from "@shopify/polaris";
import config from './config';
import AppRouter from './AppRouter';
import { createStore, applyMiddleware } from 'redux';
import { Provider as ReduxProvider } from 'react-redux';
import '@shopify/polaris/dist/styles.css';

import rootReducer from './store/reducers/rootReducer';
const store = createStore(rootReducer, []);

const paramsSearcher = new URLSearchParams(window.location.search)
const findOrigin = paramsSearcher.get('shop') || 'test.myshopify.com';

window.sessionStorage.setItem('shopifyDomain', findOrigin);

const shopifyConfig = {
    apiKey: config.API_KEY,
    shopOrigin: findOrigin
}

const CustomLinkComponent = ({children, url, ...rest}) => {
    return (
        <Link to={url} {...rest}>{children}</Link>
    );
};

ReactDOM.render(
    <React.StrictMode>
        <BrowserRouter>
            <AppBridgeProvider config={shopifyConfig}>
                <ReduxProvider store={store}>
                    <PolarisProvider i18n={enTranslations} linkComponent={CustomLinkComponent}>
                        <AppRouter />
                        <App />
                    </PolarisProvider>
                </ReduxProvider>
        </AppBridgeProvider>
        </BrowserRouter>
    </React.StrictMode>,
    document.getElementById('root')
);