Shopify App Bridge and React Router

Standard

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')
);

Shopify Polaris and the missing placeholder

Standard

I have recently been working on a Shopify app and came across a minor annoyance with a ResourceList that I solved, and then figured out why it was happening.

When adding a filter, it provides a search box, and all the examples had a placerholder in it, except mine did not have the placeholder.

While a minor thing I dug into the Shopify code and found I could pass in a queryPlaceholder property to set my own placeholder.

By setting the specific text it showed up just like I wanted. However in the component code you can see it will set a default placeholder if you don’t provide one.

When going back through the getting started directions, there is a spot to load english translations and that is what I was missing. It was an easy thing to miss but if you are missing a default placeholder, make sure you loaded the translations!